﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область ОписаниеПеременных

////////////////////////////////////////////////////////////////////////////////
// ИСПОЛЬЗУЕМЫЕ СОКРАЩЕНИЯ ИМЕН ПЕРЕМЕННЫХ (АБРЕВИАТУРЫ)

//  ПКО  - правило конвертации объектов.
//  ПКС  - правило конвертации свойств объектов.
//  ПКГС - правило конвертации группы свойств объектов.
//  ПКЗ  - правило конвертации значений объектов.
//  ПВД  - правило выгрузки данных.
//  ПОД  - правило очистки данных.

////////////////////////////////////////////////////////////////////////////////
// ВСПОМОГАТЕЛЬНЫЕ ПЕРЕМЕННЫЕ МОДУЛЯ ДЛЯ НАПИСАНИЯ АЛГОРИТМОВ (ОБЩИЕ ДЛЯ ВЫГРУЗКИ И ЗАГРУЗКИ)

Перем Конвертация  Экспорт;  // Структура свойств конвертации (Имя, Ид, обработчики событий обмена).

Перем Алгоритмы    Экспорт;  // Структура, содержащая используемые алгоритмы.
Перем Запросы      Экспорт;  // Структура, содержащая используемые запросы.
Перем ДопОбработки Экспорт;  // Структура, содержащая используемые внешние обработки.

Перем Правила      Экспорт;  // Структура, содержащая ссылки на ПКО.

Перем Менеджеры    Экспорт;  // Соответствие, содержащее поля Имя, ИмяТипа, ТипСсылкиСтрокой, Менеджер, ОбъектМД, ПКО.
Перем МенеджерыДляПлановОбмена Экспорт;
Перем ФайлОбмена Экспорт;            // Последовательно записываемый/читаемый файл обмена.

Перем ПараметрыДопОбработок Экспорт;  // Структура, содержащая параметры, используемых внешних обработок.

Перем ПараметрыИнициализированы Экспорт;  // Если Истина, то необходимые параметры конвертации проинициализированы.

Перем мФайлПротоколаДанных Экспорт; // Файл для ведения протокола обмена данными.
Перем ФлагКомментироватьОбработкуОбъектов Экспорт;

Перем ВнешняяОбработкаОбработчиковСобытий Экспорт; // Объект "ВнешниеОбработкиМенеджер" для вызова экспортных процедур
                                                   // обработчиков при отладке загрузки/выгрузки.

Перем ОбщиеПроцедурыФункции;  // Переменная хранит ссылку на данный экземпляр обработки - ЭтотОбъект.
                              // Необходима для вызова экспортных процедур из обработчиков событий.

Перем мМакетПараметровОбработчиков; // Табличный документ с параметрами обработчиков.
Перем мМакетОбщиеПроцедурыФункции;  // Текстовый документ с комментариями, глобальными переменными и обертками общих
                                    // процедур и функций.

Перем мРежимыОбработкиДанных; // Структура, содержащая режимы использования этой обработки.
Перем РежимОбработкиДанных;   // Содержит текущее значение режима обработки данных.

Перем мРежимыОтладкиАлгоритмов; // Структура, содержащая режимы отладки алгоритмов.
Перем АлгоритмыИнтегрированные; // Структура, содержащая алгоритмы с интегрированным кодом вложенных алгоритмов.

Перем ИменаОбработчиков; // Структура, содержащая имена всех обработчиков правил обмена.

Перем РазделителиКонфигурации; // Массив: содержащий разделители конфигурации.

////////////////////////////////////////////////////////////////////////////////
// ФЛАГИ НАЛИЧИЯ ГЛОБАЛЬНЫХ ОБРАБОТЧИКОВ СОБЫТИЙ

Перем ЕстьГлобальныйОбработчикПередВыгрузкойОбъекта;
Перем ЕстьГлобальныйОбработчикПослеВыгрузкиОбъекта;

Перем ЕстьГлобальныйОбработчикПередКонвертациейОбъекта;

Перем ЕстьГлобальныйОбработчикПередЗагрузкойОбъекта;
Перем ЕстьГлобальныйОбработчикПослеЗагрузкиОбъекта;

Перем ВерсияПлатформыПриемника;
Перем ПлатформаПриемника;

////////////////////////////////////////////////////////////////////////////////
// ПЕРЕМЕННЫЕ ОБРАБОТОК ОБМЕНА (ОБЩИЕ ДЛЯ ВЫГРУЗКИ И ЗАГРУЗКИ)

Перем одТипСтрока;                  // Тип("Строка")
Перем одТипБулево;                  // Тип("Булево")
Перем одТипЧисло;                   // Тип("Число")
Перем одТипДата;                    // Тип("Дата")
Перем одТипХранилищеЗначения;       // Тип("ХранилищеЗначения")
Перем одТипУникальныйИдентификатор; // Тип("УникальныйИдентификатор")
Перем одТипДвоичныеДанные;          // Тип("ДвоичныеДанные")
Перем одТипВидДвиженияНакопления;   // Тип("ВидДвиженияНакопления")
Перем одТипУдалениеОбъекта;         // Тип("УдалениеОбъекта")
Перем одТипВидСчета;			    // Тип("ВидСчета")
Перем одТипТип;			  		    // Тип("Тип")
Перем одТипСоответствие;		    // Тип("Соответствие").

Перем одТипУзлаXML_КонецЭлемента  Экспорт;
Перем одТипУзлаXML_НачалоЭлемента Экспорт;
Перем одТипУзлаXML_Текст          Экспорт;

Перем ЗначениеПустаяДата Экспорт;

Перем одСообщения;             // Соответствие. Ключ - код ошибки,  Значение - описание ошибки.

Перем мСписокМакетовПравилОбмена Экспорт;


////////////////////////////////////////////////////////////////////////////////
// ПЕРЕМЕННЫЕ МОДУЛЯ ОБРАБОТКИ ВЫГРУЗКИ
 
Перем мСчетчикВыгруженныхОбъектов Экспорт;   // Число - счетчик выгруженных объектов.
Перем мСчетчикНПП Экспорт;   // Число - счетчик НПП
Перем мТаблицаПравилКонвертацииСвойств;      // ТаблицаЗначений - шаблон для воссоздания структуры таблицы путем
                                             //                   копирования.
Перем мXMLПравила;                           // Xml-Строка, содержащая описание правил обмена.
Перем мСтрокаТиповДляПриемника;


////////////////////////////////////////////////////////////////////////////////
// ПЕРЕМЕННЫЕ МОДУЛЯ ОБРАБОТКИ ЗАГРУЗКИ
 
Перем мСчетчикЗагруженныхОбъектов Экспорт;// Число - счетчик загруженных объектов.

Перем мАтрибутыФайлаОбмена Экспорт;       // Структура. После открытия файла 
                                          // содержит атрибуты файла обмена 
                                          // согласно формату.

Перем ЗагруженныеОбъекты Экспорт;         // Соответствие. Ключ - НПП объекта в файле,
                                          // Значение - ссылка на загруженный объект.
Перем ЗагруженныеГлобальныеОбъекты Экспорт;
Перем ЧислоХранимыхЗагруженныхОбъектов Экспорт;  // Число хранимых загруженных объектов, 
                                          // после которого Соответствие ЗагруженныеОбъекты 
                                          // очищается.
Перем ЗапоминатьЗагруженныеОбъекты Экспорт;

Перем мСоответствиеДопПараметровПоиска;
Перем мСоответствиеПравилКонвертации; // Соответствие для определения правила конвертации объекта по типу этого объекта.

Перем мОбработкаДляЗагрузкиДанных Экспорт;

Перем мСоответствиеПустыхЗначенийТипов;
Перем мСоответствиеОписаниеТипов;

Перем мБылиПрочитаныПравилаОбменаПриЗагрузке Экспорт;

Перем мСтекВызововВыгрузкиДанных;

Перем мСоответствиеТиповДанныхДляЗагрузки;

Перем мГлобальныйСтекНеЗаписанныхОбъектов;

Перем СобытияПослеЗагрузкиПараметров Экспорт;

Перем ТекущийУровеньВложенностиВыгрузитьПоПравилу;

////////////////////////////////////////////////////////////////////////////////
// ПЕРЕМЕННЫЕ ДЛЯ ХРАНЕНИЯ МОДУЛЕЙ СТАНДАРТНЫХ ПОДСИСТЕМ

Перем МодульДатыЗапретаИзменения;

#КонецОбласти

#Область ПрограммныйИнтерфейс

#Область РаботаСоСтроками

// Разбирает строку на две части: до подстроки разделителя и после.
//
// Параметры:
//  Стр          - Строка - разбираемая строка;
//  Разделитель  - Строка - подстрока-разделитель:
//  Режим        - Число -0 - разделитель в возвращаемые подстроки не включается;
//                        1 - разделитель включается в левую подстроку;
//                        2 - разделитель включается в правую подстроку.
//
// Возвращаемое значение:
//  Строка - правая часть строки до символа-разделителя.
// 
Функция ОтделитьРазделителем(Стр, Знач Разделитель, Режим=0) Экспорт

	ПраваяЧасть         = "";
	ПозРазделителя      = СтрНайти(Стр, Разделитель);
	ДлинаРазделителя    = СтрДлина(Разделитель);
	Если ПозРазделителя > 0 Тогда
		ПраваяЧасть	 = Сред(Стр, ПозРазделителя + ?(Режим=2, 0, ДлинаРазделителя));
		Стр          = СокрЛП(Лев(Стр, ПозРазделителя - ?(Режим=1, -ДлинаРазделителя + 1, 1)));
	КонецЕсли;

	Возврат(ПраваяЧасть);

КонецФункции

// Преобразует значения из строки в массив, используя указанный разделитель.
//
// Параметры:
//   Стр            - Строка - разбираемая строка.
//   Разделитель    - Строка - подстрока разделитель.
//
// Возвращаемое значение:
//   Массив из Строка - полученный массив значений.
// 
Функция МассивИзСтроки(Знач Стр, Разделитель=",") Экспорт

	Массив      = Новый Массив;
	ПраваяЧасть = ОтделитьРазделителем(Стр, Разделитель);
	
	Пока Не ПустаяСтрока(Стр) Цикл
		Массив.Добавить(СокрЛП(Стр));
		Стр         = ПраваяЧасть;
		ПраваяЧасть = ОтделитьРазделителем(Стр, Разделитель);
	КонецЦикла; 

	Возврат Массив;
	
КонецФункции

// Разбивает строку на несколько строк по разделителю. Разделитель может иметь любую длину.
//
// Параметры:
//  Строка                 - Строка - текст с разделителями;
//  Разделитель            - Строка - разделитель строк текста, минимум 1 символ;
//  ПропускатьПустыеСтроки - Булево - признак необходимости включения в результат пустых строк.
//    Если параметр не задан, то функция работает в режиме совместимости со своей предыдущей версией:
//       для разделителя-пробела пустые строки не включаются в результат, для остальных разделителей пустые строки
//       включаются в результат;
//       если параметр Строка не содержит значащих символов или не содержит ни одного символа (пустая строка), то в
//       случае разделителя-пробела результатом функции будет массив, содержащий одно значение "" (пустая строка), а
//       при других разделителях результатом функции будет пустой массив.
//
//
// Возвращаемое значение:
//  Массив из Строка - массив строк.
//
// Пример:
//  РазложитьСтрокуВМассивПодстрок(",один,,два,", ",") - возвратит массив из 5 элементов, три из которых  - пустые
//  строки;
//  РазложитьСтрокуВМассивПодстрок(",один,,два,", ",", Истина) - возвратит массив из двух элементов;
//  РазложитьСтрокуВМассивПодстрок(" один   два  ", " ") - возвратит массив из двух элементов;
//  РазложитьСтрокуВМассивПодстрок("") - возвратит пустой массив;
//  РазложитьСтрокуВМассивПодстрок("",,Ложь) - возвратит массив с одним элементом "" (пустой строкой);
//  РазложитьСтрокуВМассивПодстрок("", " ") - возвратит массив с одним элементом "" (пустой строкой);
//
Функция РазложитьСтрокуВМассивПодстрок(Знач Строка, Знач Разделитель = ",", Знач ПропускатьПустыеСтроки = Неопределено) Экспорт
	
	Результат = Новый Массив;
	
	// Для обеспечения обратной совместимости.
	Если ПропускатьПустыеСтроки = Неопределено Тогда
		ПропускатьПустыеСтроки = ?(Разделитель = " ", Истина, Ложь);
		Если ПустаяСтрока(Строка) Тогда 
			Если Разделитель = " " Тогда
				Результат.Добавить("");
			КонецЕсли;
			Возврат Результат;
		КонецЕсли;
	КонецЕсли;
	//
	
	Позиция = СтрНайти(Строка, Разделитель);
	Пока Позиция > 0 Цикл
		Подстрока = Лев(Строка, Позиция - 1);
		Если Не ПропускатьПустыеСтроки Или Не ПустаяСтрока(Подстрока) Тогда
			Результат.Добавить(Подстрока);
		КонецЕсли;
		Строка = Сред(Строка, Позиция + СтрДлина(Разделитель));
		Позиция = СтрНайти(Строка, Разделитель);
	КонецЦикла;
	
	Если Не ПропускатьПустыеСтроки Или Не ПустаяСтрока(Строка) Тогда
		Результат.Добавить(Строка);
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции 

// Возвращает строку номера без символьных префиксов.
// Например:
//  ПолучитьСтроковыйНомерБезПрефиксов("УТ0000001234") = "0000001234"
//
// Параметры:
//  Номер - Строка - номер, из которого необходимо вычислить результат функции.
// 
// Возвращаемое значение:
//   Строка - строка номера без символьных префиксов.
//
Функция ПолучитьСтроковыйНомерБезПрефиксов(Номер) Экспорт
	
	НомерБезПрефиксов = "";
	Сч = СтрДлина(Номер);
	
	Пока Сч > 0 Цикл
		
		Символ = Сред(Номер, Сч, 1);
		
		Если (Символ >= "0" И Символ <= "9") Тогда
			
			НомерБезПрефиксов = Символ + НомерБезПрефиксов;
			
		Иначе
			
			Возврат НомерБезПрефиксов;
			
		КонецЕсли;
		
		Сч = Сч - 1;
		
	КонецЦикла;
	
	Возврат НомерБезПрефиксов;
	
КонецФункции

// Разбирает строку, выделяя из нее префикс и числовую часть.
//
// Параметры:
//  Стр            - Строка - разбираемая строка;
//  ЧисловаяЧасть  - Число - переменная, в которую возвратится числовая часть строки;
//  Режим          - Строка -  если "Число", то возвратит числовую часть, иначе - префикс.
//
// Возвращаемое значение:
//  Строка - префикс строки
//
Функция ПолучитьПрефиксЧислоНомера(Знач Стр, ЧисловаяЧасть = "", Режим = "") Экспорт

	ЧисловаяЧасть = 0;
	Префикс = "";
	Стр = СокрЛП(Стр);
	Длина   = СтрДлина(Стр);
	
	СтроковыйНомерБезПрефикса = ПолучитьСтроковыйНомерБезПрефиксов(Стр);
	ДлинаСтроковойЧасти = СтрДлина(СтроковыйНомерБезПрефикса);
	Если ДлинаСтроковойЧасти > 0 Тогда
		ЧисловаяЧасть = Число(СтроковыйНомерБезПрефикса);
		Префикс = Сред(Стр, 1, Длина - ДлинаСтроковойЧасти);
	Иначе
		Префикс = Стр;	
	КонецЕсли;

	Если Режим = "Число" Тогда
		Возврат(ЧисловаяЧасть);
	Иначе
		Возврат(Префикс);
	КонецЕсли;

КонецФункции

// Приводит номер (код) к требуемой длине. При этом выделяется префикс,
// и числовая часть номера, остальное пространство между префиксом и
// номером заполняется нулями.
// Функция может быть использована в обработчиках событий, программный код 
// которых хранится в правила обмена данными. Вызывается методом Выполнить().
// Сообщение "Не обнаружено ссылок на функцию" при проверке конфигурации 
// не является ошибкой проверки конфигурации.
//
// Параметры:
//  Стр          - Строка - преобразовываемая строка.
//  Длина        - Число - требуемая длина строки.
//  ДобавлятьНулиЕслиДлинаНеМеньшеТекущейДлиныНомера - Булево - признак необходимости дополнять нулями.
//  Префикс      - Строка - префикс который следует добавить к номеру.
//
// Возвращаемое значение:
//  Строка       - код или номер, приведенная к требуемой длине.
// 
Функция ПривестиНомерКДлине(Знач Стр, Длина, ДобавлятьНулиЕслиДлинаНеМеньшеТекущейДлиныНомера = Истина, Префикс = "") Экспорт

	Если ПустаяСтрока(Стр)
		ИЛИ СтрДлина(Стр) = Длина Тогда
		
		Возврат Стр;
		
	КонецЕсли;
	
	Стр             = СокрЛП(Стр);
	ВходящаяДлинаНомера = СтрДлина(Стр);

	ЧисловаяЧасть   = "";
	ПрефиксНомераСтроки   = ПолучитьПрефиксЧислоНомера(Стр, ЧисловаяЧасть);
	
	ИтоговыйПрефикс = ?(ПустаяСтрока(Префикс), ПрефиксНомераСтроки, Префикс);
	ДлинаИтоговогоПрефикса = СтрДлина(ИтоговыйПрефикс);
	
	СтрокаЧисловойЧасти = Формат(ЧисловаяЧасть, "ЧГ=0");
	ДлинаЧисловойЧасти = СтрДлина(СтрокаЧисловойЧасти);

	Если (Длина >= ВходящаяДлинаНомера И ДобавлятьНулиЕслиДлинаНеМеньшеТекущейДлиныНомера)
		ИЛИ (Длина < ВходящаяДлинаНомера) Тогда
		
		Для ВременнаяПеременная = 1 По Длина - ДлинаИтоговогоПрефикса - ДлинаЧисловойЧасти Цикл
			
			СтрокаЧисловойЧасти = "0" + СтрокаЧисловойЧасти;
			
		КонецЦикла;
	
	КонецЕсли;
	
	// обрезаем лишние символы
	СтрокаЧисловойЧасти = Прав(СтрокаЧисловойЧасти, Длина - ДлинаИтоговогоПрефикса);
		
	Результат = ИтоговыйПрефикс + СтрокаЧисловойЧасти;

	Возврат Результат;

КонецФункции

// Добавляет к префиксу номера или кода подстроку.
// Функция может быть использована в обработчиках событий, программный код 
// которых хранится в правила обмена данными. Вызывается методом Выполнить().
// Сообщение "Не обнаружено ссылок на функцию" при проверке конфигурации 
// не является ошибкой проверки конфигурации.
//
// Параметры:
//  Стр          - Строка - номер или код;
//  Добавок      - Строка - добавляемая к префиксу подстрока;
//  Длина        - Число - требуемая результирующая длина строки;
//  Режим        - Строка - "Слева" - подстрока добавляется слева к префиксу, иначе - справа.
//
// Возвращаемое значение:
//  Строка       - номер или код, к префиксу которого добавлена указанная подстрока.
//
Функция ДобавитьКПрефиксу(Знач Стр, Добавок = "", Длина = "", Режим = "Слева") Экспорт

	Стр = СокрЛП(Формат(Стр,"ЧГ=0"));

	Если ПустаяСтрока(Длина) Тогда
		Длина = СтрДлина(Стр);
	КонецЕсли;

	ЧисловаяЧасть   = "";
	Префикс         = ПолучитьПрефиксЧислоНомера(Стр, ЧисловаяЧасть);

	Если Режим = "Слева" Тогда
		Результат = СокрЛП(Добавок) + Префикс;
	Иначе
		Результат = Префикс + СокрЛП(Добавок);
	КонецЕсли;

	Пока Длина - СтрДлина(Результат) - СтрДлина(Формат(ЧисловаяЧасть, "ЧГ=0")) > 0 Цикл
		Результат = Результат + "0";
	КонецЦикла;

	Результат = Результат + Формат(ЧисловаяЧасть, "ЧГ=0");

	Возврат Результат;

КонецФункции

// Дополняет строку указанным символом до указанной длины.
//
// Параметры: 
//  Стр          - Строка - дополняемая строка;
//  Длина        - Число - требуемая длина результирующей строки;
//  Чем          - Строка - символ, которым дополняется строка.
//
// Возвращаемое значение:
//  Строка - полученная строка, дополненная указанным символом до указанной длины.
//
Функция одДополнитьСтроку(Стр, Длина, Чем = " ") Экспорт

	Результат = СокрЛП(Стр);
	Пока Длина - СтрДлина(Результат) > 0 Цикл
		Результат = Результат + Чем;
	КонецЦикла;

	Возврат(Результат);

КонецФункции

#КонецОбласти

#Область РаботаСДанными

// Возвращает строку - имя переданного значения перечисления.
// Функция может быть использована в обработчиках событий, программный код 
// которых хранится в правила обмена данными. Вызывается методом Выполнить().
// Сообщение "Не обнаружено ссылок на функцию" при проверке конфигурации 
// не является ошибкой проверки конфигурации.
//
// Параметры:
//  Значение - ПеречислениеСсылка - значение перечисления.
//
// Возвращаемое значение:
//   Строка - имя переданного значения перечисления.
//
Функция одИмяЗначенияПеречисления(Значение) Экспорт

	ОбъектМД = Значение.Метаданные();
	
	МенеджерПеречисления = Перечисления[ОбъектМД.Имя]; // ПеречислениеМенеджер
	ИндексЗначения = МенеджерПеречисления.Индекс(Значение);

	Возврат ОбъектМД.ЗначенияПеречисления.Получить(ИндексЗначения).Имя;

КонецФункции

// Определяет заполнено ли переданное значение.
//
// Параметры:
//  Значение       - Произвольный - СправочникСсылка, ДокументСсылка, Строка или любой другой тип.
//                   Значение, заполнение которого надо проверить.
//  ЭтоNULL        - Булево - в эту переменную возвращается Истина, если переданное значение NULL.
//
// Возвращаемое значение:
//   Булево - Истина         - значение не заполнено, ложь - иначе.
//
Функция одПустое(Значение, ЭтоNULL=Ложь) Экспорт

	// Сначала примитивные типы
	Если Значение = Неопределено Тогда
		Возврат Истина;
	ИначеЕсли Значение = NULL Тогда
		ЭтоNULL   = Истина;
		Возврат Истина;
	КонецЕсли;
	
	ТипЗначения = ТипЗнч(Значение);
	
	Если ТипЗначения = одТипХранилищеЗначения Тогда
		
		Результат = одПустое(Значение.Получить());
		Возврат Результат;
		
	ИначеЕсли ТипЗначения = одТипДвоичныеДанные Тогда
		
		Возврат Ложь;
		
	Иначе
		
		// Для остальных будем считать значение пустым, если оно равно
		// значению по умолчанию своего типа.
		Попытка
			Возврат Не ЗначениеЗаполнено(Значение);
		Исключение
			// На случай мутабельных значений.
			Возврат Ложь;
		КонецПопытки;
	КонецЕсли;
	
КонецФункции

// Возвращает объект ОписаниеТипов, содержащий указанный тип.
//
// Параметры:
//  ЗначениеТипа - Строка
//               - Тип - содержит имя типа или значение типа Тип.
//  
// Возвращаемое значение:
//  ОписаниеТипов - объект Описание типов.
//
Функция одОписаниеТипа(ЗначениеТипа) Экспорт
	
	ОписаниеТипов = мСоответствиеОписаниеТипов[ЗначениеТипа];
	
	Если ОписаниеТипов = Неопределено Тогда
		
		МассивТипов = Новый Массив;
		Если ТипЗнч(ЗначениеТипа) = одТипСтрока Тогда
			МассивТипов.Добавить(Тип(ЗначениеТипа));
		Иначе
			МассивТипов.Добавить(ЗначениеТипа);
		КонецЕсли; 
		ОписаниеТипов	= Новый ОписаниеТипов(МассивТипов);
		
		мСоответствиеОписаниеТипов.Вставить(ЗначениеТипа, ОписаниеТипов);
		
	КонецЕсли;
	
	Возврат ОписаниеТипов;
	
КонецФункции

// Возвращает пустое (дефолтное) значение указанного типа.
//
// Параметры:
//  Тип          - Строка
//               - Тип - имя типа или значение типа Тип.
//
// Возвращаемое значение:
//  Произвольный - пустое значение указанного типа.
// 
Функция одПолучитьПустоеЗначение(Тип) Экспорт

	ПустоеЗначениеТипа = мСоответствиеПустыхЗначенийТипов[Тип];
	
	Если ПустоеЗначениеТипа = Неопределено Тогда
		
		ПустоеЗначениеТипа = одОписаниеТипа(Тип).ПривестиЗначение(Неопределено);
		мСоответствиеПустыхЗначенийТипов.Вставить(Тип, ПустоеЗначениеТипа);
		
	КонецЕсли;
	
	Возврат ПустоеЗначениеТипа;

КонецФункции

// Осуществляет простой поиск объекта информационной базы по указанному свойству.
//
// Параметры:
//  Менеджер       - СправочникМенеджер
//                 - ДокументМенеджер - менеджер искомого объекта;
//  Свойство       - Строка - свойство, по которому осуществляем поиск: Имя, Код, 
//                   Наименование или Имя индексируемого реквизита.
//  Значение       - Строка
//                 - Число
//                 - Дата - значение свойства, по которому ищем объект.
//  НайденныйОбъектПоУникальномуИдентификатору - СправочникОбъект
//                                             - ДокументОбъект - объект информационной базы, 
//                   который был найден по уникальному идентификатору в ходе выполнения функции.
//  ОбщаяСтруктураСвойств - Структура - свойства искомого объекта.
//  ОбщиеСвойстваПоиска - Структура
//  СтрокаЗапросаПоискаПоУникальномуИдентификатору - Строка - текст запроса для поиска по уникальному идентификатору.
//
// Возвращаемое значение:
//  Произвольный - найденный объект информационной базы.
//
Функция НайтиОбъектПоСвойству(Менеджер, Свойство, Значение,
	НайденныйОбъектПоУникальномуИдентификатору,
	ОбщаяСтруктураСвойств = Неопределено, ОбщиеСвойстваПоиска = Неопределено,
	СтрокаЗапросаПоискаПоУникальномуИдентификатору = "") Экспорт
	
	Если ОбщаяСтруктураСвойств = Неопределено Тогда
		Попытка
			ТекСтруктураСвойств = Менеджеры[ТипЗнч(Менеджер.ПустаяСсылка())];
			ИмяТипа = ТекСтруктураСвойств.ИмяТипа;
		Исключение
			ИмяТипа = "";
		КонецПопытки;
	Иначе
		ИмяТипа = ОбщаяСтруктураСвойств.ИмяТипа;
	КонецЕсли;
	
	Если Свойство = "Имя" Тогда
		
		Возврат Менеджер[Значение];
		
	ИначеЕсли Свойство = "Код"
		И (ИмяТипа = "Справочник"
		ИЛИ ИмяТипа = "ПланВидовХарактеристик"
		ИЛИ ИмяТипа = "ПланСчетов"
		ИЛИ ИмяТипа = "ПланОбмена"
		ИЛИ ИмяТипа = "ПланВидовРасчета") Тогда
		
		Возврат Менеджер.НайтиПоКоду(Значение);
		
	ИначеЕсли Свойство = "Наименование"
		И (ИмяТипа = "Справочник"
		ИЛИ ИмяТипа = "ПланВидовХарактеристик"
		ИЛИ ИмяТипа = "ПланСчетов"
		ИЛИ ИмяТипа = "ПланОбмена"
		ИЛИ ИмяТипа = "ПланВидовРасчета"
		ИЛИ ИмяТипа = "Задача") Тогда
		
		Возврат Менеджер.НайтиПоНаименованию(Значение, ИСТИНА);
		
	ИначеЕсли Свойство = "Номер"
		И (ИмяТипа = "Документ"
		ИЛИ ИмяТипа = "БизнесПроцесс"
		ИЛИ ИмяТипа = "Задача") Тогда
		
		Возврат Менеджер.НайтиПоНомеру(Значение);
		
	ИначеЕсли Свойство = "{УникальныйИдентификатор}" Тогда
		
		СсылкаПоИдентификатору = Менеджер.ПолучитьСсылку(Новый УникальныйИдентификатор(Значение));
		
		Ссылка = ПроверитьСуществованиеСсылки(СсылкаПоИдентификатору, Менеджер, НайденныйОбъектПоУникальномуИдентификатору,
			СтрокаЗапросаПоискаПоУникальномуИдентификатору);
			
		Возврат Ссылка;
		
	ИначеЕсли Свойство = "{ИмяПредопределенногоЭлемента}" Тогда
		
		Попытка
			
			Ссылка = Менеджер[Значение];
			
		Исключение
			
			Ссылка = Менеджер.НайтиПоКоду(Значение);
			
		КонецПопытки;
		
		Возврат Ссылка;
		
	Иначе
		
		// Можно найти только по реквизиту, кроме строк произвольной длины и хранилища значений.
		Если НЕ (Свойство = "Дата"
			ИЛИ Свойство = "Проведен"
			ИЛИ Свойство = "ПометкаУдаления"
			ИЛИ Свойство = "Владелец"
			ИЛИ Свойство = "Родитель"
			ИЛИ Свойство = "ЭтоГруппа") Тогда
			
			Попытка
				
				СтрокаНеограниченнойДлины = ОпределитьЭтотПараметрНеограниченнойДлинны(ОбщаяСтруктураСвойств, Значение, Свойство);
				
			Исключение
				
				СтрокаНеограниченнойДлины = Ложь;
				
			КонецПопытки;
			
			Если НЕ СтрокаНеограниченнойДлины Тогда
				
				Возврат Менеджер.НайтиПоРеквизиту(Свойство, Значение);
				
			КонецЕсли;
			
		КонецЕсли;
		
		СсылкаНаОбъект = НайтиЭлементЗапросом(ОбщаяСтруктураСвойств, ОбщиеСвойстваПоиска, , Менеджер);
		Возврат СсылкаНаОбъект;
		
	КонецЕсли;
	
КонецФункции

// Осуществляет простой поиск объекта информационной базы по указанному свойству.
//
// Параметры:
//  Стр            - Строка - значение свойства, по которому осуществляется 
//                   поиск объект;
//  Тип            - Тип - тип искомого объекта;
//  Свойство       - Строка - имя свойства, по-которому ищем объект.
//
// Возвращаемое значение:
//  Произвольный - найденный объект информационной базы.
//
Функция одПолучитьЗначениеПоСтроке(Стр, Тип, Свойство = "") Экспорт

	Если ПустаяСтрока(Стр) Тогда
		Возврат Новый(Тип);
	КонецЕсли; 

	Свойства = Менеджеры[Тип];

	Если Свойства = Неопределено Тогда
		
		ОписаниеТипов = одОписаниеТипа(Тип);
		Возврат ОписаниеТипов.ПривестиЗначение(Стр);
		
	КонецЕсли;

	Если ПустаяСтрока(Свойство) Тогда
		
		Если Свойства.ИмяТипа = "Перечисление" Тогда
			Свойство = "Имя";
		Иначе
			Свойство = "{ИмяПредопределенногоЭлемента}";
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат НайтиОбъектПоСвойству(Свойства.Менеджер, Свойство, Стр, Неопределено);
	
КонецФункции

// Возвращает строковое представление типа значения.
//
// Параметры: 
//  ЗначениеИлиТип - Произвольный - значение любого типа или Тип.
//
// Возвращаемое значение:
//  Строка - строковое представление типа значения.
//
Функция одТипЗначенияСтрокой(ЗначениеИлиТип) Экспорт

	ТипЗначения	= ТипЗнч(ЗначениеИлиТип);
	
	Если ТипЗначения = одТипТип Тогда
		ТипЗначения	= ЗначениеИлиТип;
	КонецЕсли; 
	
	Если (ТипЗначения = Неопределено) Или (ЗначениеИлиТип = Неопределено) Тогда
		Результат = "";
	ИначеЕсли ТипЗначения = одТипСтрока Тогда
		Результат = "Строка";
	ИначеЕсли ТипЗначения = одТипЧисло Тогда
		Результат = "Число";
	ИначеЕсли ТипЗначения = одТипДата Тогда
		Результат = "Дата";
	ИначеЕсли ТипЗначения = одТипБулево Тогда
		Результат = "Булево";
	ИначеЕсли ТипЗначения = одТипХранилищеЗначения Тогда
		Результат = "ХранилищеЗначения";
	ИначеЕсли ТипЗначения = одТипУникальныйИдентификатор Тогда
		Результат = "УникальныйИдентификатор";
	ИначеЕсли ТипЗначения = одТипВидДвиженияНакопления Тогда
		Результат = "ВидДвиженияНакопления";
	Иначе
		Менеджер = Менеджеры[ТипЗначения];
		Если Менеджер = Неопределено Тогда
			
			Текст= НСтр("ru = 'Неизвестный тип:'") + Строка(ТипЗнч(ТипЗначения));
			СообщитьПользователю(Текст);
			
		Иначе
			Результат = Менеджер.ТипСсылкиСтрокой;
		КонецЕсли;
	КонецЕсли;

	Возврат Результат;
	
КонецФункции

// Возвращает XML представление объекта ОписаниеТипов.
// Функция может быть использована в обработчиках событий, программный код 
// которых хранится в правила обмена данными.
// Параметры:
//  ОписаниеТипов  - ОписаниеТипов - объект ОписаниеТипов, XML представление которого требуется получить.
//
// Возвращаемое значение:
//  Строка - XML представление переданного объекта ОписаниеТипов.
//
Функция одПолучитьXMLПредставлениеОписанияТипов(ОписаниеТипов) Экспорт
	
	УзелТипов = СоздатьУзел("Типы");
	
	Если ТипЗнч(ОписаниеТипов) = Тип("Структура") Тогда
		УстановитьАтрибут(УзелТипов, "ДопустимыйЗнак",          СокрЛП(ОписаниеТипов.ДопустимыйЗнак));
		УстановитьАтрибут(УзелТипов, "Разрядность",             СокрЛП(ОписаниеТипов.Разрядность));
		УстановитьАтрибут(УзелТипов, "РазрядностьДробнойЧасти", СокрЛП(ОписаниеТипов.РазрядностьДробнойЧасти));
		УстановитьАтрибут(УзелТипов, "Длина",                   СокрЛП(ОписаниеТипов.Длина));
		УстановитьАтрибут(УзелТипов, "ДопустимаяДлина",         СокрЛП(ОписаниеТипов.ДопустимаяДлина));
		УстановитьАтрибут(УзелТипов, "СоставДаты",              СокрЛП(ОписаниеТипов.ЧастиДаты));
		
		Для каждого СтрТип Из ОписаниеТипов.Типы Цикл
			УзелТипа = СоздатьУзел("Тип");
			УзелТипа.ЗаписатьТекст(СокрЛП(СтрТип));
			ДобавитьПодчиненный(УзелТипов, УзелТипа);
		КонецЦикла;
	Иначе
		КвЧисла       = ОписаниеТипов.КвалификаторыЧисла;
		КвСтроки      = ОписаниеТипов.КвалификаторыСтроки;
		КвДаты        = ОписаниеТипов.КвалификаторыДаты;
		
		УстановитьАтрибут(УзелТипов, "ДопустимыйЗнак",          СокрЛП(КвЧисла.ДопустимыйЗнак));
		УстановитьАтрибут(УзелТипов, "Разрядность",             СокрЛП(КвЧисла.Разрядность));
		УстановитьАтрибут(УзелТипов, "РазрядностьДробнойЧасти", СокрЛП(КвЧисла.РазрядностьДробнойЧасти));
		УстановитьАтрибут(УзелТипов, "Длина",                   СокрЛП(КвСтроки.Длина));
		УстановитьАтрибут(УзелТипов, "ДопустимаяДлина",         СокрЛП(КвСтроки.ДопустимаяДлина));
		УстановитьАтрибут(УзелТипов, "СоставДаты",              СокрЛП(КвДаты.ЧастиДаты));
		
		Для каждого Тип Из ОписаниеТипов.Типы() Цикл
			УзелТипа = СоздатьУзел("Тип");
			УзелТипа.ЗаписатьТекст(одТипЗначенияСтрокой(Тип));
			ДобавитьПодчиненный(УзелТипов, УзелТипа);
		КонецЦикла;
	КонецЕсли;
	
	УзелТипов.ЗаписатьКонецЭлемента();
	
	Возврат(УзелТипов.Закрыть());
	
КонецФункции

#КонецОбласти

#Область ПроцедурыИФункцииДляРаботыСОбъектомXMLЗапись

// Заменяет недопустимые символы XML на другой символ.
//
// Параметры:
//       Текст - Строка - текст, в котором следует заменить символы.
//       СимволЗамены - Строка - значение на которое следует заменять недопустимые символы.
// Возвращаемое значение:
//       Строка - результат замены.
//
Функция ЗаменитьНедопустимыеСимволыXML(Знач Текст, СимволЗамены = " ") Экспорт
	
	Позиция = НайтиНедопустимыеСимволыXML(Текст);
	Пока Позиция > 0 Цикл
		Текст = СтрЗаменить(Текст, Сред(Текст, Позиция, 1), СимволЗамены);
		Позиция = НайтиНедопустимыеСимволыXML(Текст);
	КонецЦикла;
	
	Возврат Текст;
КонецФункции

// Создает новый xml-узел
// Функция может быть использована в обработчиках событий, программный код. 
// которых хранится в правила обмена данными. Вызывается методом Выполнить().
//
// Параметры: 
//   Имя - Строка - имя узла.
//
// Возвращаемое значение:
//   ЗаписьXML - объект нового xml-узла.
//
Функция СоздатьУзел(Имя) Экспорт

	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.УстановитьСтроку();
	ЗаписьXML.ЗаписатьНачалоЭлемента(Имя);

	Возврат ЗаписьXML;

КонецФункции

// Добавляет новый xml-узел к указанному узлу-родителю.
// Функция может быть использована в обработчиках событий, программный код 
// которых хранится в правила обмена данными. Вызывается методом Выполнить().
// Сообщение "Не обнаружено ссылок на функцию" при проверке конфигурации 
// не является ошибкой проверки конфигурации.
//
// Параметры: 
//  УзелРодитель   - ЗаписьXML - xml-узел-родитель.
//  Имя            - Строка - имя добавляемого узла.
//
// Возвращаемое значение:
//  ЗаписьXML - xml-узел, добавленный к указанному узлу-родителю.
//
Функция ДобавитьУзел(УзелРодитель, Имя) Экспорт

	УзелРодитель.ЗаписатьНачалоЭлемента(Имя);

	Возврат УзелРодитель;

КонецФункции

// Копирует указанный xml-узел.
// Функция может быть использована в обработчиках событий, программный код 
// которых хранится в правила обмена данными. Вызывается методом Выполнить().
// Сообщение "Не обнаружено ссылок на функцию" при проверке конфигурации 
// не является ошибкой проверки конфигурации.
//
// Параметры: 
//  Узел - ЗаписьXML - xml узел.
//
// Возвращаемое значение:
//  ЗаписьXML - копия указанного узла.
//
Функция КопироватьУзел(Узел) Экспорт

	Стр = Узел.Закрыть();

	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.УстановитьСтроку();
	
	Если ВестиДополнительныйКонтрольЗаписиВXML Тогда
		
		Стр = ОбщегоНазначенияКлиентСервер.УдалитьНедопустимыеСимволыXML(Стр);
		
	КонецЕсли;
	
	ЗаписьXML.ЗаписатьБезОбработки(Стр);

	Возврат ЗаписьXML;
	
КонецФункции

// Осуществляет запись элемента и его значения в указанный объект.
//
// Параметры:
//  Объект         - ЗаписьXML - объект типа XMLЗапись.
//  Имя            - Строка - имя элемента.
//  Значение       - Произвольный - значение элемента.
//
Процедура одЗаписатьЭлемент(Объект, Имя, Значение="") Экспорт

	Объект.ЗаписатьНачалоЭлемента(Имя);
	Стр = XMLСтрока(Значение);
	
	Если ВестиДополнительныйКонтрольЗаписиВXML Тогда
		
		Стр =  ОбщегоНазначенияКлиентСервер.УдалитьНедопустимыеСимволыXML(Стр);
		
	КонецЕсли;
	
	Объект.ЗаписатьТекст(Стр);
	Объект.ЗаписатьКонецЭлемента();
	
КонецПроцедуры

// Подчиняет xml-узел указанному узлу-родителю.
//
// Параметры: 
//  УзелРодитель   - ЗаписьXML - xml узел-родитель.
//  Узел           - ЗаписьXML - xml узел подчиняемый.
//
Процедура ДобавитьПодчиненный(УзелРодитель, Узел) Экспорт

	Если ТипЗнч(Узел) <> одТипСтрока Тогда
		Узел.ЗаписатьКонецЭлемента();
		ИнформацияДляЗаписиВФайл = Узел.Закрыть();
	Иначе
		ИнформацияДляЗаписиВФайл = Узел;
	КонецЕсли;
	
	УзелРодитель.ЗаписатьБезОбработки(ИнформацияДляЗаписиВФайл);
		
КонецПроцедуры

// Устанавливает атрибут указанного xml-узла.
//
// Параметры: 
//  Узел           - ЗаписьXML - xml-узел
//  Имя            - Строка - имя атрибута.
//  Значение       - Произвольный - устанавливаемое значение.
//
Процедура УстановитьАтрибут(Узел, Имя, Значение) Экспорт

	СтрокаЗаписи = XMLСтрока(Значение);
	
	Если ВестиДополнительныйКонтрольЗаписиВXML Тогда
		
		СтрокаЗаписи = ОбщегоНазначенияКлиентСервер.УдалитьНедопустимыеСимволыXML(СтрокаЗаписи);
		
	КонецЕсли;
	
	Узел.ЗаписатьАтрибут(Имя, СтрокаЗаписи);
	
КонецПроцедуры

#КонецОбласти

#Область ПроцедурыИФункцииДляРаботыСОбъектомXMLЧтение

// Читает значение атрибута по имени из указанного объекта, приводит значение
// к указанному примитивному типу.
//
// Параметры:
//  Объект      - ЧтениеXML - объект типа XMLЧтение, спозиционированный на начале элемента,
//                атрибут которого требуется получить.
//  Тип         - Тип - тип атрибута.
//  Имя         - Строка - имя атрибута.
//
// Возвращаемое значение:
//  Произвольный - значение атрибута полученное по имени и приведенное к указанному типу.
//
Функция одАтрибут(Объект, Тип, Имя) Экспорт

	СтрЗначение = Объект.ПолучитьАтрибут(Имя);
	Если Не ПустаяСтрока(СтрЗначение) Тогда
		Возврат XMLЗначение(Тип, СокрП(СтрЗначение));
	ИначеЕсли      Тип = одТипСтрока Тогда
		Возврат ""; 
	ИначеЕсли Тип = одТипБулево Тогда
		Возврат Ложь;
	ИначеЕсли Тип = одТипЧисло Тогда
		Возврат 0;
	ИначеЕсли Тип = одТипДата Тогда
		Возврат ЗначениеПустаяДата;
	КонецЕсли;
		
КонецФункции
 
// Пропускает узлы xml до конца указанного элемента (по умолчанию текущего).
//
// Параметры:
//  Объект   - ЧтениеXML - объект типа XMLЧтение.
//  Имя      - Строка - имя узла, до конца которого пропускаем элементы.
//
Процедура одПропустить(Объект, Имя = "") Экспорт

	КоличествоВложений = 0; // Количество одноименных вложений.

	Если Имя = "" Тогда
		
		Имя = Объект.ЛокальноеИмя;
		
	КонецЕсли; 
	
	Пока Объект.Прочитать() Цикл
		
		Если Объект.ЛокальноеИмя <> Имя Тогда
			Продолжить;
		КонецЕсли;
		
		ТипУзла = Объект.ТипУзла;
			
		Если ТипУзла = одТипУзлаXML_КонецЭлемента Тогда
				
			Если КоличествоВложений = 0 Тогда
					
				Прервать;
					
			Иначе
					
				КоличествоВложений = КоличествоВложений - 1;
					
			КонецЕсли;
				
		ИначеЕсли ТипУзла = одТипУзлаXML_НачалоЭлемента Тогда
				
			КоличествоВложений = КоличествоВложений + 1;
				
		КонецЕсли;
					
	КонецЦикла;
	
КонецПроцедуры

// Читает текст элемента и приводит значение к указанному типу.
//
// Параметры:
//  Объект           - ЧтениеXML - объект типа XMLЧтение, из которого осуществляется чтение.
//  Тип              - Тип - тип получаемого значения.
//  ИскатьПоСвойству - Строка - для ссылочных типов может быть указано свойство, по которому.
//                     следует искать объект: "Код", "Наименование", <ИмяРеквизита>, "Имя" (предопределенного значения).
//  ОбрезатьСтрокуСправа - Булево - признак необходимости обрезать строку справа.
//
// Возвращаемое значение:
//  Произвольный - значение xml-элемента, приведенное к соответствующему типу.
//
Функция одЗначениеЭлемента(Объект, Тип, ИскатьПоСвойству = "", ОбрезатьСтрокуСправа = Истина) Экспорт

	Значение = "";
	Имя      = Объект.ЛокальноеИмя;

	Пока Объект.Прочитать() Цикл
		
		ТипУзла = Объект.ТипУзла;
		
		Если ТипУзла = одТипУзлаXML_Текст Тогда
			
			Значение = Объект.Значение;
			
			Если ОбрезатьСтрокуСправа Тогда
				
				Значение = СокрП(Значение);
				
			КонецЕсли;
						
		ИначеЕсли (Объект.ЛокальноеИмя = Имя) И (ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			
			Прервать;
			
		Иначе
			
			Возврат Неопределено;
			
		КонецЕсли;
		
	КонецЦикла;

	
	Если (Тип = одТипСтрока)
		ИЛИ (Тип = одТипБулево)
		ИЛИ (Тип = одТипЧисло)
		ИЛИ (Тип = одТипДата)
		ИЛИ (Тип = одТипХранилищеЗначения)
		ИЛИ (Тип = одТипУникальныйИдентификатор)
		ИЛИ (Тип = одТипВидДвиженияНакопления)
		ИЛИ (Тип = одТипВидСчета) Тогда
		
		Возврат XMLЗначение(Тип, Значение);
		
	Иначе
		
		Возврат одПолучитьЗначениеПоСтроке(Значение, Тип, ИскатьПоСвойству);
		
	КонецЕсли;
	
КонецФункции

#КонецОбласти

#Область ПроцедурыИФункцииРаботыСФайломОбмена

// Сохраняет в файл указанный xml-узел.
//
// Параметры:
//  Узел - ЗаписьXML - xml-узел, сохраняемый в файл.
//
Процедура ЗаписатьВФайл(Узел) Экспорт

	Если ТипЗнч(Узел) <> одТипСтрока Тогда
		ИнформацияДляЗаписиВФайл = Узел.Закрыть();
	Иначе
		ИнформацияДляЗаписиВФайл = Узел;
	КонецЕсли;
	
	Если НепосредственноеЧтениеВИБПриемнике Тогда
		
		СтрокаОшибкиВБазеПриемнике = "";
		ПередатьИнформациюОЗаписиВПриемник(ИнформацияДляЗаписиВФайл, СтрокаОшибкиВБазеПриемнике);
		Если Не ПустаяСтрока(СтрокаОшибкиВБазеПриемнике) Тогда
			
			ВызватьИсключение СтрокаОшибкиВБазеПриемнике;
			
		КонецЕсли;
		
	Иначе
		
		ФайлОбмена.ЗаписатьСтроку(ИнформацияДляЗаписиВФайл);
		
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ПроцедурыИФункцииРаботыСПротоколомОбмена

// Возвращает объект типа структура, содержащий все возможные поля
// записи протокола выполнения (сообщения об ошибках и т.п.).
//
// Параметры:
//  КодСообщения - Строка - код сообщения.
//  СтрокаОшибки - Строка - строковое содержание ошибки.
//
// Возвращаемое значение:
//  Структура - все возможные поля записи протокола выполнения.
//
Функция ПолучитьСтруктуруЗаписиПротокола(КодСообщения = "", СтрокаОшибки = "") Экспорт

	СтруктураОшибки = Новый Структура(
		"ИмяПКО,
		|ИмяПОД,
		|Нпп,
		|Гнпп,
		|Источник,
		|ТипОбъекта,
		|Свойство,
		|Значение,
		|ТипЗначения,
		|ПКО,
		|ПКС,
		|ПКГС,
		|ПВД,
		|ПОД,
		|Объект,
		|СвойствоПриемника,
		|КонвертируемоеЗначение,
		|Обработчик,
		|ОписаниеОшибки,
		|ПозицияМодуля,
		|Текст,
		|КодСообщения,
		|УзелПланаОбмена");
	
	СтрокаМодуля = ОтделитьРазделителем(СтрокаОшибки, "{");
	Если ПустаяСтрока(СтрокаОшибки) Тогда
		ОписаниеОшибки = СокрЛП(ОтделитьРазделителем(СтрокаМодуля, "}:"));
	Иначе
		ОписаниеОшибки = СтрокаОшибки;
		СтрокаМодуля   = "{" + СтрокаМодуля;
	КонецЕсли;
	
	Если ОписаниеОшибки <> "" Тогда
		СтруктураОшибки.ОписаниеОшибки = ОписаниеОшибки;
		СтруктураОшибки.ПозицияМодуля  = СтрокаМодуля;
	КонецЕсли;
	
	Если СтруктураОшибки.КодСообщения <> "" Тогда
		
		СтруктураОшибки.КодСообщения = КодСообщения;
		
	КонецЕсли;
	
	Возврат СтруктураОшибки;
	
КонецФункции 

// Записывает информацию об ошибке в протокол выполнения обмена.
//
// Параметры:
//  КодСообщения - Строка - код сообщения.
//  СтрокаОшибки - Строка - строковое содержание ошибки.
//  Объект - Произвольный - объект, к которому относится ошибка.
//  ТипОбъекта - Тип - тип объекта к которому относится ошибка.
//
// Возвращаемое значение:
//  Строка - строка ошибки.
//
Функция ЗаписатьИнформациюОбОшибкеВПротокол(КодСообщения, СтрокаОшибки, Объект, ТипОбъекта = Неопределено) Экспорт
	
	ЗП         = ПолучитьСтруктуруЗаписиПротокола(КодСообщения, СтрокаОшибки);
	ЗП.Объект  = Объект;
	
	Если ТипОбъекта <> Неопределено Тогда
		ЗП.ТипОбъекта     = ТипОбъекта;
	КонецЕсли;	
		
	СтрокаОшибки = ЗаписатьВПротоколВыполнения(КодСообщения, ЗП);	
	
	Возврат СтрокаОшибки;	
	
КонецФункции

// Регистрирует в протоколе выполнения ошибку обработчика ПКО (загрузка).
//
// Параметры:
//  КодСообщения - Строка - код сообщения.
//  СтрокаОшибки - Строка - строковое содержание ошибки.
//  ИмяПравила - Строка - имя правила конвертации объекта.
//  Источник - Произвольный - источник при конвертации которого возникла ошибка.
//  ТипОбъекта - Тип - тип объекта при конвертации которого возникла ошибка.
//  Объект - Произвольный - объект, полученный в результате конвертации.
//  ИмяОбработчика - Строка - имя обработчика в котором возникла ошибка.
//
Процедура ЗаписатьИнформациюОбОшибкеЗагрузкиОбработчикаПКО(КодСообщения, СтрокаОшибки, ИмяПравила, Источник,
	ТипОбъекта, Объект, ИмяОбработчика) Экспорт
	
	ЗП            = ПолучитьСтруктуруЗаписиПротокола(КодСообщения, СтрокаОшибки);
	ЗП.ИмяПКО     = ИмяПравила;
	ЗП.ТипОбъекта = ТипОбъекта;
	ЗП.Обработчик = ИмяОбработчика;
	
	Если Не ПустаяСтрока(Источник) Тогда
		
		ЗП.Источник = Источник;
		
	КонецЕсли;
	
	Если Объект <> Неопределено Тогда
		
		ЗП.Объект = Строка(Объект);
		
	КонецЕсли;
	
	СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(КодСообщения, ЗП);
	
	Если Не ФлагРежимОтладки Тогда
		ВызватьИсключение СтрокаСообщенияОбОшибке;
	КонецЕсли;
	
КонецПроцедуры

// Регистрирует в протоколе выполнения ошибку обработчика ПКС.
//
// Параметры:
//  КодСообщения - Строка - код сообщения.
//  СтрокаОшибки - Строка - строковое содержание ошибки.
//  ПКО - СтрокаТаблицыЗначений - правило конвертации объекта.
//  ПКС - СтрокаТаблицыЗначений - правило конвертации свойства.
//  Источник - Произвольный - источник при конвертации которого возникла ошибка. 
//  ИмяОбработчика - Строка - имя обработчика в котором возникла ошибка.
//  Значение - Произвольный - значение, при конвертации которого возникла ошибка.
//  ЭтоПКС - Булево - ошибка возникла при обработке правила конвертации свойств.
//
Процедура ЗаписатьИнформациюОбОшибкеОбработчикиПКС(КодСообщения, СтрокаОшибки, ПКО, ПКС, Источник = "", 
	ИмяОбработчика = "", Значение = Неопределено, ЭтоПКС = Истина) Экспорт
	
	ЗП                        = ПолучитьСтруктуруЗаписиПротокола(КодСообщения, СтрокаОшибки);
	ЗП.ПКО                    = ПКО.Имя + "  (" + ПКО.Наименование + ")";
	
	ИмяПравила = ПКС.Имя + "  (" + ПКС.Наименование + ")";
	Если ЭтоПКС Тогда
		ЗП.ПКС                = ИмяПравила;
	Иначе
		ЗП.ПКГС               = ИмяПравила;
	КонецЕсли;
	
	ОписаниеТипов = Новый ОписаниеТипов("Строка");
	ИсточникСтрока  = ОписаниеТипов.ПривестиЗначение(Источник);
	Если Не ПустаяСтрока(ИсточникСтрока) Тогда
		ЗП.Объект = ИсточникСтрока + "  (" + ТипЗнч(Источник) + ")";
	Иначе
		ЗП.Объект = "(" + ТипЗнч(Источник) + ")";
	КонецЕсли;
	
	Если ЭтоПКС Тогда
		ЗП.СвойствоПриемника      = ПКС.Приемник + "  (" + ПКС.ТипПриемника + ")";
	КонецЕсли;
	
	Если ИмяОбработчика <> "" Тогда
		ЗП.Обработчик         = ИмяОбработчика;
	КонецЕсли;
	
	Если Значение <> Неопределено Тогда
		ЗП.КонвертируемоеЗначение = Строка(Значение) + "  (" + ТипЗнч(Значение) + ")";
	КонецЕсли;
	
	СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(КодСообщения, ЗП);
	
	Если Не ФлагРежимОтладки Тогда
		ВызватьИсключение СтрокаСообщенияОбОшибке;
	КонецЕсли;
		
КонецПроцедуры

#КонецОбласти

#Область ПроцедурыСозданияИнтерфейсаВызоваОбработчиковВПравилахОбмена

// Дополняет имеющиеся коллекции с правилами обмена интерфейсами вызова обработчиков.
//
// Параметры:
//  СтруктураКонвертация - Структура - содержит правила конвертации и глобальные обработчики.
//  ТаблицаПКО           - ТаблицаЗначений - содержит правила конвертации объектов.
//  ТаблицаПВД           - ДеревоЗначений - содержит правила выгрузки данных.
//  ТаблицаПОД           - ДеревоЗначений - содержит правила очистки данных.
//  
Процедура ДополнитьПравилаИнтерфейсамиОбработчиков(СтруктураКонвертация, ТаблицаПКО, ТаблицаПВД, ТаблицаПОД) Экспорт
	
	мМакетПараметровОбработчиков = ПолучитьМакет("ПараметрыОбработчиков");
	
	// Добавляем интерфейсы Конвертации (глобальные).
	ДополнитьИнтерфейсамиОбработчиковПравилаКонвертации(СтруктураКонвертация);
	
	// Добавляем интерфейсы ПВД
	ДополнитьИнтерфейсамиОбработчиковПравилаВыгрузкиДанных(ТаблицаПВД, ТаблицаПВД.Строки);
	
	// Добавляем интерфейсы ПОД
	ДополнитьИнтерфейсамиОбработчиковПравилаОчисткиДанных(ТаблицаПОД, ТаблицаПОД.Строки);
	
	// Добавляем интерфейсы ПКО, ПКС, ПКГС.
	ДополнитьИнтерфейсамиОбработчиковПравилаКонвертацииОбъектов(ТаблицаПКО);
	
КонецПроцедуры 

#КонецОбласти

#Область ПроцедурыРаботыСПравиламиОбмена

// Осуществляет поиск правила конвертации по имени или в соответствии с типом
// переданного объекта.
//
// Параметры:
//   Объект - Произвольный - объект-источник, для которого ищем правило конвертации.
//   ИмяПравила - Строка - имя правила конвертации.
//
// Возвращаемое значение:
//   СтрокаТаблицыЗначений - ссылка на правило конвертации (строка в таблице правил):
//     * Имя - Строка
//     * Наименование - Строка
//     * Источник - Строка
//     * Свойства - см. КоллекцияПравилаКонвертацииСвойств
// 
Функция НайтиПравило(Объект = Неопределено, ИмяПравила = "") Экспорт

	Если Не ПустаяСтрока(ИмяПравила) Тогда
		
		Правило = Правила[ИмяПравила]; // см. НайтиПравило
		
	Иначе
		
		Правило = Менеджеры[ТипЗнч(Объект)];
		Если Правило <> Неопределено Тогда
			Правило = Правило.ПКО; // см. НайтиПравило
			
			Если Правило <> Неопределено Тогда
				ИмяПравила = Правило.Имя;
			КонецЕсли;
			
		КонецЕсли; 
		
	КонецЕсли;
	
	Возврат Правило; 
	
КонецФункции

// Сохраняет правила обмена во внутреннем формате.
//
Процедура СохранитьПравилаВоВнутреннемФормате() Экспорт

	Для Каждого Правило Из ТаблицаПравилКонвертации Цикл
		Правило.Выгруженные.Очистить();
		Правило.ВыгруженныеТолькоСсылки.Очистить();
	КонецЦикла;

	СтруктураПравил = ОписаниеСтруктурыПравил();
	
	// Сохраняем запросы
	ЗапросыДляСохранения = Новый Структура;
	Для Каждого ЭлементСтруктуры Из Запросы Цикл
		ЗапросыДляСохранения.Вставить(ЭлементСтруктуры.Ключ, ЭлементСтруктуры.Значение.Текст);
	КонецЦикла;

	ПараметрыДляСохранения = Новый Структура;
	Для Каждого ЭлементСтруктуры Из Параметры Цикл
		ПараметрыДляСохранения.Вставить(ЭлементСтруктуры.Ключ, Неопределено);
	КонецЦикла;

	СтруктураПравил.ТаблицаПравилВыгрузки = ТаблицаПравилВыгрузки;
	СтруктураПравил.ТаблицаПравилКонвертации = ТаблицаПравилКонвертации;
	СтруктураПравил.Алгоритмы = Алгоритмы;
	СтруктураПравил.Запросы = ЗапросыДляСохранения;
	СтруктураПравил.Конвертация = Конвертация;
	СтруктураПравил.мXMLПравила = мXMLПравила;
	СтруктураПравил.ТаблицаНастройкиПараметров = ТаблицаНастройкиПараметров;
	СтруктураПравил.Параметры = ПараметрыДляСохранения;
	
	СтруктураПравил.Вставить("ВерсияПлатформыПриемника",   ВерсияПлатформыПриемника);
	
	СохраненныеНастройки  = Новый ХранилищеЗначения(СтруктураПравил);
	
КонецПроцедуры

// Устанавливает значения параметров в структуре Параметры 
// по таблице ТаблицаНастройкиПараметров.
//
Процедура УстановитьПараметрыИзДиалога() Экспорт

	Для Каждого СтрокаТаблицы Из ТаблицаНастройкиПараметров Цикл
		Параметры.Вставить(СтрокаТаблицы.Имя, СтрокаТаблицы.Значение);
	КонецЦикла;

КонецПроцедуры

// Устанавливает значение параметра в таблице параметров в форме обработки.
//
// Параметры:
//   ИмяПараметра - Строка - имя параметра.
//   ЗначениеПараметра - Произвольный - значение параметра.
//
Процедура УстановитьЗначениеПараметраВТаблице(ИмяПараметра, ЗначениеПараметра) Экспорт
	
	СтрокаТаблицы = ТаблицаНастройкиПараметров.Найти(ИмяПараметра, "Имя");
	
	Если СтрокаТаблицы <> Неопределено Тогда
		
		СтрокаТаблицы.Значение = ЗначениеПараметра;	
		
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ОбработкаПравилОчистки

// Производит удаление (или помечает на удаление) объект выборки в соответствии с указанным правилом.
//
// Параметры:
//  Объект         - Произвольный - удаляемый (помечаемый на удаление) объект выборки.
//  Правило        - СтрокаТаблицыЗначений - ссылка на правило очистки данных.
//  Свойства       - Структура - свойства объекта метаданного удаляемого объекта.
//  ВходящиеДанные - Произвольный - произвольные вспомогательные данные.
// 
Процедура УдалениеОбъектаВыборки(Объект, Правило, Свойства=Неопределено, ВходящиеДанные=Неопределено) Экспорт

	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	Отказ                  = Ложь;
	УдалитьНепосредственно = Правило.Непосредственно;
	
	
	// Обработчик ПередУдалениемОбъектаВыборки
	Если Не ПустаяСтрока(Правило.ПередУдалением) Тогда
	
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(Правило, "ПередУдалением"));
				
			Иначе
				
				Выполнить(Правило.ПередУдалением);
				
			КонецЕсли;
			
		Исключение
			
			ЗаписатьИнформациюОбОшибкеОбработчикаОчисткиДанных(29, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				Правило.Имя, Объект, "ПередУдалениемОбъектаВыборки");
			
		КонецПопытки;
		
		Если Отказ Тогда
		
			Возврат;
			
		КонецЕсли;
		
	КонецЕсли;
	
	
	Попытка
		
		ВыполнитьУдалениеОбъекта(Объект, Свойства, УдалитьНепосредственно);
		
	Исключение
		
		ЗаписатьИнформациюОбОшибкеОбработчикаОчисткиДанных(24, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
			Правило.Имя, Объект, "");
		
	КонецПопытки;

КонецПроцедуры

#КонецОбласти

#Область ПроцедурыВыгрузкиДанных

// Производит выгрузку объекта в соответствии с указанным правилом конвертации.
//
// Параметры:
//  Источник				 - Произвольный - источник данных.
//  Приемник				 - ЗаписьXML - xml-узел объекта приемника.
//  ВходящиеДанные			 - Произвольный - произвольные вспомогательные данные, 
//                             для выполнения конвертации.
//  ИсходящиеДанные			 - Произвольный - произвольные вспомогательные данные, передаваемые правилам
//                             передаваемые правилу конвертации свойств.
//  ИмяПКО					 - Строка - имя правила конвертации, согласно которому осуществляется выгрузка.
//  УзелСсылки				 - ЗаписьXML - xml-узел ссылки объекта приемника.
//  ТолькоПолучитьУзелСсылки - Булево - если Истина, то выгрузка объекта не производится, 
//                             только формируется xml-узел ссылки.
//  ПКО						 - СтрокаТаблицыЗначений - строка таблицы правил конвертации.
//  ЭтоПравилоСГлобальнойВыгрузкойОбъектов - Булево - признак правила с глобальной выгрузкой объектов.
//  ВыборкаДляВыгрузкиДанных - ВыборкаИзРезультатаЗапроса - выборка содержащая данные для выгрузки. 
//
// Возвращаемое значение:
//   ЗаписьXML - xml-узел ссылки или значение приемника.
//
Функция ВыгрузитьПоПравилу(Источник					= Неопределено,
						   Приемник					= Неопределено,
						   ВходящиеДанные			= Неопределено,
						   ИсходящиеДанные			= Неопределено,
						   ИмяПКО					= "",
						   УзелСсылки				= Неопределено,
						   ТолькоПолучитьУзелСсылки	= Ложь,
						   ПКО						= Неопределено,
						   ЭтоПравилоСГлобальнойВыгрузкойОбъектов = Ложь,
						   ВыборкаДляВыгрузкиДанных = Неопределено) Экспорт
	
	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	// Поиск ПКО
	Если ПКО = Неопределено Тогда
		
		ПКО = НайтиПравило(Источник, ИмяПКО);
		
	ИначеЕсли (Не ПустаяСтрока(ИмяПКО))
		И ПКО.Имя <> ИмяПКО Тогда
		
		ПКО = НайтиПравило(Источник, ИмяПКО);
				
	КонецЕсли;	
	
	Если ПКО = Неопределено Тогда
		
		ЗП = ПолучитьСтруктуруЗаписиПротокола(45);
		
		ЗП.Объект = Источник;
		ЗП.ТипОбъекта = ТипЗнч(Источник);
		
		ЗаписатьВПротоколВыполнения(45, ЗП, Истина); // не найдено ПКО
		Возврат Неопределено;
		
	КонецЕсли;

	ТекущийУровеньВложенностиВыгрузитьПоПравилу = ТекущийУровеньВложенностиВыгрузитьПоПравилу + 1;
	
	Если ФлагКомментироватьОбработкуОбъектов Тогда
		
		ОписаниеТипа = Новый ОписаниеТипов("Строка");
		ИсточникВСтроку = ОписаниеТипа.ПривестиЗначение(Источник);
		ИсточникВСтроку = ?(ИсточникВСтроку = "", " ", ИсточникВСтроку);
		
		ПрОбъекта = ИсточникВСтроку + "  (" + ТипЗнч(Источник) + ")";
		
		СтрокаНазванияПКО = " ПКО: " + СокрЛП(ИмяПКО) + "  (" + СокрЛП(ПКО.Наименование) + ")";
		
		СтрокаПользователю = ?(ТолькоПолучитьУзелСсылки, НСтр("ru = 'Конвертация ссылки на объект: %1'"), НСтр("ru = 'Конвертация объекта: %1'"));
		СтрокаПользователю = ПодставитьПараметрыВСтроку(СтрокаПользователю, ПрОбъекта);
		
		ЗаписатьВПротоколВыполнения(СтрокаПользователю + СтрокаНазванияПКО, , Ложь, ТекущийУровеньВложенностиВыгрузитьПоПравилу + 1, 7);
		
	КонецЕсли;
	
	ЭтоПравилоСГлобальнойВыгрузкойОбъектов = ВыполнитьОбменДаннымиВОптимизированномФормате И ПКО.ИспользоватьБыстрыйПоискПриЗагрузке;

    ЗапоминатьВыгруженные       = ПКО.ЗапоминатьВыгруженные;
	ВыгруженныеОбъекты          = ПКО.Выгруженные;
	ВыгруженныеОбъектыТолькоСсылки = ПКО.ВыгруженныеТолькоСсылки;
	ВсеОбъектыВыгружены         = ПКО.ВсеОбъектыВыгружены;
	НеЗамещатьОбъектПриЗагрузке = ПКО.НеЗамещать;
	НеСоздаватьЕслиНеНайден     = ПКО.НеСоздаватьЕслиНеНайден;
	ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD     = ПКО.ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD;
	
	ПрефиксАвтонумерации		= "";
	РежимЗаписи     			= "";
	РежимПроведения 			= "";
	СписокВременныхФайлов = Неопределено;

   	ИмяТипа          = "";
	СтруктураСвойств = Менеджеры[ПКО.Источник];
	Если СтруктураСвойств = Неопределено Тогда
		СтруктураСвойств = Менеджеры[ТипЗнч(Источник)];
	КонецЕсли;
	
	Если СтруктураСвойств <> Неопределено Тогда
		ИмяТипа = СтруктураСвойств.ИмяТипа;
	КонецЕсли;

	// КлючВыгружаемыхДанных
	
	Если (Источник <> Неопределено) И ЗапоминатьВыгруженные Тогда
		Если ИмяТипа = "РегистрСведений" ИЛИ ИмяТипа = "Константы" ИЛИ ПустаяСтрока(ИмяТипа) Тогда
			ЗапоминатьВыгруженные = Ложь;
		Иначе
			КлючВыгружаемыхДанных = ЗначениеВСтрокуВнутр(Источник);
		КонецЕсли;
	Иначе
		КлючВыгружаемыхДанных = ИмяПКО;
		ЗапоминатьВыгруженные = Ложь;
	КонецЕсли;
	
	
	// Переменная для хранения имени предопределенного элемента.
	ИмяПредопределенногоЭлемента = Неопределено;

	// Глобальный обработчик ПередКонвертациейОбъекта.
    Отказ = Ложь;	
	Если ЕстьГлобальныйОбработчикПередКонвертациейОбъекта Тогда
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(Конвертация, "ПередКонвертациейОбъекта"));

			Иначе
				
				Выполнить(Конвертация.ПередКонвертациейОбъекта);
				
			КонецЕсли;
			
		Исключение
			
			ИмяОбработчика = НСтр("ru = '%1 (глобальный)'");
			ЗаписатьИнформациюОбОшибкеВыгрузкиОбработчикаПКО(64, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				ПКО, Источник, ПодставитьПараметрыВСтроку(ИмяОбработчика, "ПередКонвертациейОбъекта"));
				
		КонецПопытки;
		
		Если Отказ Тогда	//	Отказ от дальнейшей обработки правила.
			ТекущийУровеньВложенностиВыгрузитьПоПравилу = ТекущийУровеньВложенностиВыгрузитьПоПравилу - 1;
			Возврат Приемник;
		КонецЕсли;
		
	КонецЕсли;
	
	// Обработчик ПередВыгрузкой
	Если ПКО.ЕстьОбработчикПередВыгрузкой Тогда
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКО, "ПередВыгрузкой"));
				
			Иначе
				
				Выполнить(ПКО.ПередВыгрузкой);
				
			КонецЕсли;
			
		Исключение
			ЗаписатьИнформациюОбОшибкеВыгрузкиОбработчикаПКО(41, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				ПКО, Источник, "ПередВыгрузкойОбъекта");
		КонецПопытки;
		
		Если Отказ Тогда	//	Отказ от дальнейшей обработки правила.
			ТекущийУровеньВложенностиВыгрузитьПоПравилу = ТекущийУровеньВложенностиВыгрузитьПоПравилу - 1;
			Возврат Приемник;
		КонецЕсли;
		
	КонецЕсли;
	
	// Возможно такие данные уже выгружались.
	Если Не ВсеОбъектыВыгружены Тогда
		
		НПП = 0;
		
		Если ЗапоминатьВыгруженные Тогда
			
			УзелСсылки = ВыгруженныеОбъекты[КлючВыгружаемыхДанных];
			Если УзелСсылки <> Неопределено Тогда
				
				Если ТолькоПолучитьУзелСсылки Тогда
					ТекущийУровеньВложенностиВыгрузитьПоПравилу = ТекущийУровеньВложенностиВыгрузитьПоПравилу - 1;
					Возврат УзелСсылки;
				КонецЕсли;
				
				НомерВыгруженнойСсылки = ВыгруженныеОбъектыТолькоСсылки[КлючВыгружаемыхДанных];
				Если НомерВыгруженнойСсылки = Неопределено Тогда
					ТекущийУровеньВложенностиВыгрузитьПоПравилу = ТекущийУровеньВложенностиВыгрузитьПоПравилу - 1;
					Возврат УзелСсылки;
				Иначе
					
					СтрокаВСтекеВыгрузки = КоллекцияСтекВызововВыгрузкиДанных().Найти(КлючВыгружаемыхДанных, "Ссылка");
				
					Если СтрокаВСтекеВыгрузки <> Неопределено Тогда
						ТекущийУровеньВложенностиВыгрузитьПоПравилу = ТекущийУровеньВложенностиВыгрузитьПоПравилу - 1;
						Возврат УзелСсылки;
					КонецЕсли;
					
					СтрокаВСтекеВыгрузки = КоллекцияСтекВызововВыгрузкиДанных().Добавить();
					СтрокаВСтекеВыгрузки.Ссылка = КлючВыгружаемыхДанных;
					
					НПП = НомерВыгруженнойСсылки;
				КонецЕсли;
			КонецЕсли;
			
		КонецЕсли;
		
		Если НПП = 0 Тогда
			
			мСчетчикНПП = мСчетчикНПП + 1;
			НПП         = мСчетчикНПП;
			
		КонецЕсли;
		
		// Это позволит избежать циклических ссылок.
		Если ЗапоминатьВыгруженные Тогда
			
			ВыгруженныеОбъекты[КлючВыгружаемыхДанных] = НПП;
			Если ТолькоПолучитьУзелСсылки Тогда
				ВыгруженныеОбъектыТолькоСсылки[КлючВыгружаемыхДанных] = НПП;
			Иначе
				
				СтрокаВСтекеВыгрузки = КоллекцияСтекВызововВыгрузкиДанных().Добавить();
				СтрокаВСтекеВыгрузки.Ссылка = КлючВыгружаемыхДанных;
				
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЕсли;
	
	СоответствиеЗначений = ПКО.Значения;
	КоличествоЭлементовСоответствияЗначений = СоответствиеЗначений.Количество();
	
	// Обработка  соответствий предопределенных элементов.
	Если ПлатформаПриемника = "V8" Тогда
		
		// Если имя предопределенного элемента пока не определено, то попытаемся его определить.
		Если ИмяПредопределенногоЭлемента = Неопределено Тогда
			
			Если СтруктураСвойств <> Неопределено
				И КоличествоЭлементовСоответствияЗначений > 0
				И СтруктураСвойств.ВозможенПоискПоПредопределенным Тогда
			
				Попытка
					ИмяПредопределенногоИсточник = ИмяПредопределенного(Источник);
				Исключение
					ИмяПредопределенногоИсточник = "";
				КонецПопытки;
				
			Иначе
				
				ИмяПредопределенногоИсточник = "";
				
			КонецЕсли;
			
			Если НЕ ПустаяСтрока(ИмяПредопределенногоИсточник)
				И КоличествоЭлементовСоответствияЗначений > 0 Тогда
				
				ИмяПредопределенногоЭлемента = СоответствиеЗначений[Источник];
				
			Иначе
				ИмяПредопределенногоЭлемента = Неопределено;
			КонецЕсли;
			
		КонецЕсли;
		
		Если ИмяПредопределенногоЭлемента <> Неопределено Тогда
			КоличествоЭлементовСоответствияЗначений = 0;
		КонецЕсли;
		
	Иначе
		ИмяПредопределенногоЭлемента = Неопределено;
	КонецЕсли;
	
	НеНужноВыгружатьПоСоответствиюЗначений = (КоличествоЭлементовСоответствияЗначений = 0);
	
	Если Не НеНужноВыгружатьПоСоответствиюЗначений Тогда
		
		// Если нет объекта в соответствии значений - выгружаем его штатным образом.
		УзелСсылки = СоответствиеЗначений[Источник];
		Если УзелСсылки = Неопределено
			И ПКО.СвойстваПоиска.Количество() > 0 Тогда
			
			// Возможно это конвертация из перечисления в перечисление и мы просто не нашли по.
			// ПКЗ нужное свойство - тогда просто выгружаем пустую ссылку и все.
			Если СтруктураСвойств.ИмяТипа = "Перечисление"
				И СтрНайти(ПКО.Приемник, "ПеречислениеСсылка.") > 0 Тогда
				
				УзелСсылки = "";
				
			Иначе
						
				НеНужноВыгружатьПоСоответствиюЗначений = Истина;	
				
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЕсли;
	
	НужноЗапоминатьОбъект = ЗапоминатьВыгруженные И (Не ВсеОбъектыВыгружены);

	Если НеНужноВыгружатьПоСоответствиюЗначений Тогда
		
		Если ПКО.СвойстваПоиска.Количество() > 0 
			ИЛИ ИмяПредопределенногоЭлемента <> Неопределено Тогда
			
			//	Формируем узел ссылки
			УзелСсылки = СоздатьУзел("Ссылка");
			
			Если НужноЗапоминатьОбъект Тогда
				
				Если ЭтоПравилоСГлобальнойВыгрузкойОбъектов Тогда
					УстановитьАтрибут(УзелСсылки, "ГНпп", НПП);
				Иначе
					УстановитьАтрибут(УзелСсылки, "Нпп", НПП);
				КонецЕсли;
				
			КонецЕсли;
			
			ВыгрузитьТолькоСсылку = ПКО.НеВыгружатьОбъектыСвойствПоСсылкам ИЛИ ТолькоПолучитьУзелСсылки;
			
			Если НеСоздаватьЕслиНеНайден Тогда
				УстановитьАтрибут(УзелСсылки, "НеСоздаватьЕслиНеНайден", НеСоздаватьЕслиНеНайден);
			КонецЕсли;
			
			Если ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD Тогда
				УстановитьАтрибут(УзелСсылки, "ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD", ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD);
			КонецЕсли;
			
			ВыгрузитьСвойства(Источник, Приемник, ВходящиеДанные, ИсходящиеДанные, ПКО, ПКО.СвойстваПоиска, 
				УзелСсылки, ВыборкаДляВыгрузкиДанных, ИмяПредопределенногоЭлемента, ВыгрузитьТолькоСсылку);
			
			УзелСсылки.ЗаписатьКонецЭлемента();
			УзелСсылки = УзелСсылки.Закрыть();
			
			Если НужноЗапоминатьОбъект Тогда
				
				ВыгруженныеОбъекты[КлючВыгружаемыхДанных] = УзелСсылки;
				
			КонецЕсли;
			
		Иначе
			УзелСсылки = НПП;
		КонецЕсли;
		
	Иначе
		
		// Поиск в соответствии значений по ПКЗ.
		Если УзелСсылки = Неопределено Тогда
			// По Соответствию значений не нашли - пробуем найти по свойствам поиска.
			СтруктураЗаписи = Новый Структура("Источник,ТипИсточника", Источник, ТипЗнч(Источник));
			ЗаписатьВПротоколВыполнения(71, СтруктураЗаписи);
			Если СтрокаВСтекеВыгрузки <> Неопределено Тогда
				мСтекВызововВыгрузкиДанных.Удалить(СтрокаВСтекеВыгрузки);
			КонецЕсли;
			ТекущийУровеньВложенностиВыгрузитьПоПравилу = ТекущийУровеньВложенностиВыгрузитьПоПравилу - 1;
			Возврат Неопределено;
		КонецЕсли;
		
		Если ЗапоминатьВыгруженные Тогда
			ВыгруженныеОбъекты[КлючВыгружаемыхДанных] = УзелСсылки;
		КонецЕсли;
		
		Если СтрокаВСтекеВыгрузки <> Неопределено Тогда
			мСтекВызововВыгрузкиДанных.Удалить(СтрокаВСтекеВыгрузки);
		КонецЕсли;
		ТекущийУровеньВложенностиВыгрузитьПоПравилу = ТекущийУровеньВложенностиВыгрузитьПоПравилу - 1;
		Возврат УзелСсылки;
		
	КонецЕсли;
	
	Если ТолькоПолучитьУзелСсылки Или ВсеОбъектыВыгружены Тогда
	
		Если СтрокаВСтекеВыгрузки <> Неопределено Тогда
			мСтекВызововВыгрузкиДанных.Удалить(СтрокаВСтекеВыгрузки);
		КонецЕсли;
		ТекущийУровеньВложенностиВыгрузитьПоПравилу = ТекущийУровеньВложенностиВыгрузитьПоПравилу - 1;
		Возврат УзелСсылки;
		
	КонецЕсли;

	Если Приемник = Неопределено Тогда
		
		Приемник = СоздатьУзел("Объект");
		
		Если ЭтоПравилоСГлобальнойВыгрузкойОбъектов Тогда
			УстановитьАтрибут(Приемник, "ГНпп", НПП);
		Иначе
			УстановитьАтрибут(Приемник, "Нпп", НПП);
		КонецЕсли;
		
		УстановитьАтрибут(Приемник, "Тип", 			ПКО.Приемник);
		УстановитьАтрибут(Приемник, "ИмяПравила",	ПКО.Имя);
		
		Если НеЗамещатьОбъектПриЗагрузке Тогда
			УстановитьАтрибут(Приемник, "НеЗамещать",	"true");
		КонецЕсли;
		
		Если Не ПустаяСтрока(ПрефиксАвтонумерации) Тогда
			УстановитьАтрибут(Приемник, "ПрефиксАвтонумерации",	ПрефиксАвтонумерации);
		КонецЕсли;
		
		Если Не ПустаяСтрока(РежимЗаписи) Тогда
			УстановитьАтрибут(Приемник, "РежимЗаписи",	РежимЗаписи);
			Если Не ПустаяСтрока(РежимПроведения) Тогда
				УстановитьАтрибут(Приемник, "РежимПроведения",	РежимПроведения);
			КонецЕсли;
		КонецЕсли;
		
		Если ТипЗнч(УзелСсылки) <> одТипЧисло Тогда
			ДобавитьПодчиненный(Приемник, УзелСсылки);
		КонецЕсли; 
		
	КонецЕсли;

	// Обработчик ПриВыгрузке
	СтандартнаяОбработка = Истина;
	Отказ = Ложь;
	
	Если ПКО.ЕстьОбработчикПриВыгрузке Тогда
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКО, "ПриВыгрузке"));
				
			Иначе
				
				Выполнить(ПКО.ПриВыгрузке);
				
			КонецЕсли;
			
		Исключение
			ЗаписатьИнформациюОбОшибкеВыгрузкиОбработчикаПКО(42, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				ПКО, Источник, "ПриВыгрузкеОбъекта");
		КонецПопытки;
		
		Если Отказ Тогда	//	Отказ от записи объекта в файл.
			Если СтрокаВСтекеВыгрузки <> Неопределено Тогда
				мСтекВызововВыгрузкиДанных.Удалить(СтрокаВСтекеВыгрузки);
			КонецЕсли;
			ТекущийУровеньВложенностиВыгрузитьПоПравилу = ТекущийУровеньВложенностиВыгрузитьПоПравилу - 1;
			Возврат УзелСсылки;
		КонецЕсли;
		
	КонецЕсли;

	// Выгрузка свойств
	Если СтандартнаяОбработка Тогда
		
		ВыгрузитьСвойства(Источник, Приемник, ВходящиеДанные, ИсходящиеДанные, ПКО, ПКО.Свойства, , ВыборкаДляВыгрузкиДанных, ,
			ПКО.НеВыгружатьОбъектыСвойствПоСсылкам ИЛИ ТолькоПолучитьУзелСсылки, СписокВременныхФайлов);
			
	КонецЕсли;
	
	// Обработчик ПослеВыгрузки
	Если ПКО.ЕстьОбработчикПослеВыгрузки Тогда
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКО, "ПослеВыгрузки"));
				
			Иначе
				
				Выполнить(ПКО.ПослеВыгрузки);
				
			КонецЕсли;
			
		Исключение
			ЗаписатьИнформациюОбОшибкеВыгрузкиОбработчикаПКО(43, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				ПКО, Источник, "ПослеВыгрузкиОбъекта");
		КонецПопытки;
		
		Если Отказ Тогда	//	Отказ от записи объекта в файл.
			
			Если СтрокаВСтекеВыгрузки <> Неопределено Тогда
				мСтекВызововВыгрузкиДанных.Удалить(СтрокаВСтекеВыгрузки);
			КонецЕсли;
			ТекущийУровеньВложенностиВыгрузитьПоПравилу = ТекущийУровеньВложенностиВыгрузитьПоПравилу - 1;
			Возврат УзелСсылки;
			
		КонецЕсли;
		
	КонецЕсли;
	
	Если СписокВременныхФайлов = Неопределено Тогда
	
		//	Запись объекта в файл
		Приемник.ЗаписатьКонецЭлемента();
		ЗаписатьВФайл(Приемник);
		
	Иначе
		
		ЗаписатьВФайл(Приемник);
		
		ПеренестиДанныеИзВременныхФайлов(СписокВременныхФайлов);
		
		ЗаписатьВФайл("</Объект>");
		
	КонецЕсли;
	
	мСчетчикВыгруженныхОбъектов = 1 + мСчетчикВыгруженныхОбъектов;
	
	Если НужноЗапоминатьОбъект Тогда
				
		Если ЭтоПравилоСГлобальнойВыгрузкойОбъектов Тогда
			ВыгруженныеОбъекты[КлючВыгружаемыхДанных] = НПП;
		КонецЕсли;
		
	КонецЕсли;
	
	Если СтрокаВСтекеВыгрузки <> Неопределено Тогда
		мСтекВызововВыгрузкиДанных.Удалить(СтрокаВСтекеВыгрузки);
	КонецЕсли;
	
	ТекущийУровеньВложенностиВыгрузитьПоПравилу = ТекущийУровеньВложенностиВыгрузитьПоПравилу - 1;
	
	// Обработчик ПослеВыгрузкиВФайл
	Если ПКО.ЕстьОбработчикПослеВыгрузкиВФайл Тогда
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКО, "ПослеВыгрузкиВФайл"));
				
			Иначе
				
				Выполнить(ПКО.ПослеВыгрузкиВФайл);
				
			КонецЕсли;
			
		Исключение
			ЗаписатьИнформациюОбОшибкеВыгрузкиОбработчикаПКО(76, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				ПКО, Источник, "ЕстьОбработчикПослеВыгрузкиВФайл");
		КонецПопытки;
				
	КонецЕсли;
	
	Возврат УзелСсылки;

КонецФункции

// Возвращает фрагмент текста языка запросов, который выражает условие ограничения на интервал дат.
//
// Параметры:
//   Свойства - Структура - свойства объекта метаданных.
//   ИмяТипа - Строка - имя типа.
//   ИмяГруппыТаблицы - Строка - имя группы таблицы.
//   ВыборкаДляОчисткиДанных - Булево - выборка для очистки данных.
//
// Возвращаемое значение:
//     Строка - фрагмент запроса с условием ограничения на интервал дат.
//
Функция ПолучитьСтрокуОграниченияПоДатеДляЗапроса(Свойства, ИмяТипа, ИмяГруппыТаблицы = "", ВыборкаДляОчисткиДанных = Ложь) Экспорт
	
	ИтоговоеОграничениеПоДате = "";
	
	Если НЕ (ИмяТипа = "Документ" ИЛИ ИмяТипа = "РегистрСведений") Тогда
		Возврат ИтоговоеОграничениеПоДате;
	КонецЕсли;
	
	Если ИмяТипа = "РегистрСведений" Тогда
		
		Непериодический = НЕ Свойства.Периодический;
		НеНужноОграничениеПоДатам = ВыборкаДляОчисткиДанных	ИЛИ Непериодический;
		
		Если НеНужноОграничениеПоДатам Тогда
			Возврат ИтоговоеОграничениеПоДате;
		КонецЕсли;
				
	КонецЕсли;	
	
	Если ПустаяСтрока(ИмяГруппыТаблицы) Тогда
		ИмяПоляОграничения = ?(ИмяТипа = "Документ", "Дата", "Период");
	Иначе
		ИмяПоляОграничения = ИмяГруппыТаблицы + "." + ?(ИмяТипа = "Документ", "Дата", "Период");
	КонецЕсли;
	
	Если ДатаНачала <> ЗначениеПустаяДата Тогда
		
		ИтоговоеОграничениеПоДате = "
		|	ГДЕ
		|		" + ИмяПоляОграничения + " >= &ДатаНачала";
		
	КонецЕсли;
		
	Если ДатаОкончания <> ЗначениеПустаяДата Тогда
		
		Если ПустаяСтрока(ИтоговоеОграничениеПоДате) Тогда
			
			ИтоговоеОграничениеПоДате = "
			|	ГДЕ
			|		" + ИмяПоляОграничения + " <= &ДатаОкончания";
			
		Иначе
			
			ИтоговоеОграничениеПоДате = ИтоговоеОграничениеПоДате + "
			|	И
			|		" + ИмяПоляОграничения + " <= &ДатаОкончания";
			
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат ИтоговоеОграничениеПоДате;
	
КонецФункции

// Формирует результат запроса для выгрузки очистки данных.
// 
// Параметры:
//   Свойства - см. СтруктураПараметровМенеджера.
//   ИмяТипа - Строка - имя типа.
//   ВыборкаДляОчисткиДанных - Булево - выборка для очистки данных.
//   УдалятьОбъектыНепосредственно - Булево - признак необходимости непосредственного удаления.
//   ВыбиратьВсеПоля - Булево - признак необходимости выбирать все поля.
//
// Возвращаемое значение:
//   РезультатЗапроса, Неопределено - результат запроса для выгрузки очистки данных.
//
Функция ПолучитьРезультатЗапросаДляВыгрузкиОчисткиДанных(Свойства, ИмяТипа, 
	ВыборкаДляОчисткиДанных = Ложь, УдалятьОбъектыНепосредственно = Ложь, ВыбиратьВсеПоля = Истина) Экспорт 
	
	СтрокаРазрешения = ?(ВыгружатьТолькоРазрешенные, " РАЗРЕШЕННЫЕ ", ""); // @Query-part-1
	СтрокаВыбораПолей = ?(ВыбиратьВсеПоля, " * ", "	ОбъектДляВыгрузки.Ссылка КАК Ссылка ");
	
	Если ИмяТипа = "Справочник"
		Или ИмяТипа = "ПланВидовХарактеристик" 
		Или ИмяТипа = "ПланСчетов" 
		Или ИмяТипа = "ПланВидовРасчета" 
		Или ИмяТипа = "РегистрБухгалтерии"
		Или ИмяТипа = "ПланОбмена"
		Или ИмяТипа = "Задача"
		Или ИмяТипа = "БизнесПроцесс" Тогда
		
		Запрос = Новый Запрос;
		
		Если ИмяТипа = "Справочник" Тогда
			МетаданныеОбъектов = Метаданные.Справочники[Свойства.Имя];
		ИначеЕсли ИмяТипа = "ПланВидовХарактеристик" Тогда
		    МетаданныеОбъектов = Метаданные.ПланыВидовХарактеристик[Свойства.Имя];
		ИначеЕсли ИмяТипа = "ПланСчетов" Тогда
		    МетаданныеОбъектов = Метаданные.ПланыСчетов[Свойства.Имя];
		ИначеЕсли ИмяТипа = "ПланВидовРасчета" Тогда
		    МетаданныеОбъектов = Метаданные.ПланыВидовРасчета[Свойства.Имя];
		ИначеЕсли ИмяТипа = "РегистрБухгалтерии" Тогда
		    МетаданныеОбъектов = Метаданные.РегистрыБухгалтерии[Свойства.Имя];
		ИначеЕсли ИмяТипа = "ПланОбмена" Тогда
		    МетаданныеОбъектов = Метаданные.ПланыОбмена[Свойства.Имя];
		ИначеЕсли ИмяТипа = "Задача" Тогда
		    МетаданныеОбъектов = Метаданные.Задачи[Свойства.Имя];
		ИначеЕсли ИмяТипа = "БизнесПроцесс" Тогда
		    МетаданныеОбъектов = Метаданные.БизнесПроцессы[Свойства.Имя];
		КонецЕсли;
		
		Если ИмяТипа = "РегистрБухгалтерии" Тогда
			
			СтрокаВыбораПолей = " * ";
			ИмяТаблицыДляВыборки = Свойства.Имя + ".ДвиженияССубконто";
			
		Иначе
			
			ИмяТаблицыДляВыборки = Свойства.Имя;
			
			Если ВыгружатьТолькоРазрешенные
				И НЕ ВыбиратьВсеПоля Тогда
				
				ИмяПервогоРеквизита = ПолучитьИмяПервогоРеквизитаМетаданных(МетаданныеОбъектов);
				Если Не ПустаяСтрока(ИмяПервогоРеквизита) Тогда
					СтрокаВыбораПолей = СтрокаВыбораПолей + ", ОбъектДляВыгрузки." + ИмяПервогоРеквизита;
				КонецЕсли;
				
			КонецЕсли;
			
		КонецЕсли;
		
		Запрос.Текст =
		"ВЫБРАТЬ РАЗРЕШЕННЫЕ
		| *
		|ИЗ
		|	&ИмяТаблицыМетаданных КАК ОбъектДляВыгрузки";
		
		Если ПустаяСтрока(СтрокаРазрешения) Тогда
			
			Запрос.Текст = СтрЗаменить(Запрос.Текст, "ВЫБРАТЬ РАЗРЕШЕННЫЕ", "ВЫБРАТЬ");
			
		КонецЕсли;
		
		Если СокрЛП(СтрокаВыбораПолей) <> "*" Тогда
			
			Запрос.Текст = СтрЗаменить(Запрос.Текст, "*", СтрокаВыбораПолей);
			
		КонецЕсли;
		
		СтрокаИмяТаблицыМетаданных = ПодставитьПараметрыВСтроку("%1.%2", ИмяТипа, ИмяТаблицыДляВыборки);
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ИмяТаблицыМетаданных", СтрокаИмяТаблицыМетаданных);
		
	ИначеЕсли ИмяТипа = "Документ" Тогда
		
		Если ВыгружатьТолькоРазрешенные Тогда
			
			ИмяПервогоРеквизита = ПолучитьИмяПервогоРеквизитаМетаданных(Метаданные.Документы[Свойства.Имя]);
			Если Не ПустаяСтрока(ИмяПервогоРеквизита) Тогда
				СтрокаВыбораПолей = СтрокаВыбораПолей + ", ОбъектДляВыгрузки." + ИмяПервогоРеквизита;
			КонецЕсли;
			
		КонецЕсли;
		
		ИтоговоеОграничениеПоДате = ПолучитьСтрокуОграниченияПоДатеДляЗапроса(Свойства, ИмяТипа, "ОбъектДляВыгрузки", ВыборкаДляОчисткиДанных);
		
		Запрос = Новый Запрос;
		Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
		Запрос.УстановитьПараметр("ДатаОкончания", ДатаОкончания);
		
		Запрос.Текст =
		"ВЫБРАТЬ РАЗРЕШЕННЫЕ
		| *
		|ИЗ
		|	&ИмяТаблицыМетаданных КАК ОбъектДляВыгрузки";
		
		Если ПустаяСтрока(СтрокаРазрешения) Тогда
			
			Запрос.Текст = СтрЗаменить(Запрос.Текст, "ВЫБРАТЬ РАЗРЕШЕННЫЕ", "ВЫБРАТЬ");
			
		КонецЕсли;
		
		Если СокрЛП(СтрокаВыбораПолей) <> "*" Тогда
			
			Запрос.Текст = СтрЗаменить(Запрос.Текст, "*", СтрокаВыбораПолей);
			
		КонецЕсли;
		
		СтрокаИмяТаблицыМетаданных = ПодставитьПараметрыВСтроку("%1.%2", ИмяТипа, Свойства.Имя);
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ИмяТаблицыМетаданных", СтрокаИмяТаблицыМетаданных);
		Запрос.Текст = Запрос.Текст + Символы.ПС + ИтоговоеОграничениеПоДате;
		
	ИначеЕсли ИмяТипа = "РегистрСведений" Тогда
		
		ИтоговоеОграничениеПоДате = ПолучитьСтрокуОграниченияПоДатеДляЗапроса(Свойства, ИмяТипа, "ОбъектДляВыгрузки", ВыборкаДляОчисткиДанных);
		
		Запрос = Новый Запрос;
		Запрос.УстановитьПараметр("ДатаНачала", ДатаНачала);
		Запрос.УстановитьПараметр("ДатаОкончания", ДатаОкончания);
		
		Запрос.Текст =
		"ВЫБРАТЬ РАЗРЕШЕННЫЕ
		| *
		|
		|,NULL КАК Активность
		|,NULL КАК Регистратор
		|,NULL КАК НомерСтроки
		|,NULL КАК Период
		|
		|ИЗ
		|	&ИмяТаблицыМетаданных КАК ОбъектДляВыгрузки";
		
		Если Свойства.ПодчиненныйРегистратору Тогда
			
			Запрос.Текст = СтрЗаменить(Запрос.Текст, ",NULL КАК Активность", "");
			Запрос.Текст = СтрЗаменить(Запрос.Текст, ",NULL КАК Регистратор", "");
			Запрос.Текст = СтрЗаменить(Запрос.Текст, ",NULL КАК НомерСтроки", "");
			
		КонецЕсли;
		
		Если Свойства.Периодический Тогда
			
			Запрос.Текст = СтрЗаменить(Запрос.Текст, ",NULL КАК Период", "");
			
		КонецЕсли;
		
		Если ПустаяСтрока(СтрокаРазрешения) Тогда
			
			Запрос.Текст = СтрЗаменить(Запрос.Текст, "ВЫБРАТЬ РАЗРЕШЕННЫЕ", "ВЫБРАТЬ");
			
		КонецЕсли;
		
		СтрокаИмяТаблицыМетаданных = ПодставитьПараметрыВСтроку("%1.%2", ИмяТипа, Свойства.Имя);
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ИмяТаблицыМетаданных", СтрокаИмяТаблицыМетаданных);
		Запрос.Текст = Запрос.Текст + Символы.ПС + ИтоговоеОграничениеПоДате;
		
	Иначе
		
		Возврат Неопределено;
		
	КонецЕсли;
	
	Возврат Запрос.Выполнить();
	
КонецФункции

// Формирует выборку для выгрузки очистки данных.
//
// Параметры:
//   Свойства - Структура - свойства объекта метаданных.
//   ИмяТипа - Строка - имя типа.
//   ВыборкаДляОчисткиДанных - Булево - выборка для очистки данных.
//   УдалятьОбъектыНепосредственно - Булево - признак необходимости удалять непосредственно.
//   ВыбиратьВсеПоля - Булево - признак необходимости выбирать все поля.
//
// Возвращаемое значение:
//   ВыборкаИзРезультатаЗапроса - выборка для выгрузки очистки данных.
//
Функция ПолучитьВыборкуДляВыгрузкиОчисткиДанных(Свойства, ИмяТипа, 
	ВыборкаДляОчисткиДанных = Ложь, УдалятьОбъектыНепосредственно = Ложь, ВыбиратьВсеПоля = Истина) Экспорт
	
	РезультатЗапроса = ПолучитьРезультатЗапросаДляВыгрузкиОчисткиДанных(Свойства, ИмяТипа, 
			ВыборкаДляОчисткиДанных, УдалятьОбъектыНепосредственно, ВыбиратьВсеПоля);
			
	Если РезультатЗапроса = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
			
	Выборка = РезультатЗапроса.Выбрать();
	
	Возврат Выборка;
	
КонецФункции

#КонецОбласти

#Область ЭкспортируемыеПроцедурыИФункции

// Заполняет переданную таблицу значений типами объектов метаданных для удаления, на которые есть право доступа для
// удаления.
//
// Параметры:
//   ТаблицаДанных - ТаблицаЗначений - таблица для заполнения.
//
Процедура ЗаполнитьСписокТиповДоступныхДляУдаления(ТаблицаДанных) Экспорт
	
	ТаблицаДанных.Очистить();
	
	Для каждого ОбъектМД Из Метаданные.Справочники Цикл
		
		Если Не ПравоДоступа("Удаление", ОбъектМД) Тогда
			Продолжить;
		КонецЕсли;
		
		СтрокаТаблицы = ТаблицаДанных.Добавить();
		СтрокаТаблицы.Метаданные = "СправочникСсылка." + ОбъектМД.Имя;
		
	КонецЦикла;

	Для каждого ОбъектМД Из Метаданные.ПланыВидовХарактеристик Цикл
		
		Если Не ПравоДоступа("Удаление", ОбъектМД) Тогда
			Продолжить;
		КонецЕсли;
		
		СтрокаТаблицы = ТаблицаДанных.Добавить();
		СтрокаТаблицы.Метаданные = "ПланВидовХарактеристикСсылка." + ОбъектМД.Имя;
	КонецЦикла;

	Для Каждого ОбъектМД Из Метаданные.Документы Цикл
		
		Если Не ПравоДоступа("Удаление", ОбъектМД) Тогда
			Продолжить;
		КонецЕсли;
		
		СтрокаТаблицы = ТаблицаДанных.Добавить();
		СтрокаТаблицы.Метаданные = "ДокументСсылка." + ОбъектМД.Имя;
	КонецЦикла;

	Для каждого ОбъектМД Из Метаданные.РегистрыСведений Цикл
		
		Если Не ПравоДоступа("Удаление", ОбъектМД) Тогда
			Продолжить;
		КонецЕсли;
		
		Подчинен		=	(ОбъектМД.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору);
		Если Подчинен Тогда Продолжить КонецЕсли;
		
		СтрокаТаблицы = ТаблицаДанных.Добавить();
		СтрокаТаблицы.Метаданные = "РегистрСведенийЗапись." + ОбъектМД.Имя;
		
	КонецЦикла;
	
КонецПроцедуры

// Устанавливает состояние пометки у подчиненных строк строки дерева значений
// в зависимости от пометки текущей строки.
//
// Параметры:
//  ТекСтрока      - СтрокаДереваЗначений - строка, у которой следует обработать подчиненные строки.
//  Реквизит       - Строка - имя реквизита, в котором содержится пометка.
// 
Процедура УстановитьПометкиПодчиненных(ТекСтрока, Реквизит) Экспорт

	Подчиненные = ТекСтрока.Строки;

	Если Подчиненные.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	Для Каждого Строка Из Подчиненные Цикл
		
		Если Строка.НастройкиПостроителя = Неопределено 
			И Реквизит = "ИспользоватьОтбор" Тогда
			
			Строка[Реквизит] = 0;
			
		Иначе
			
			Строка[Реквизит] = ТекСтрока[Реквизит];
			
		КонецЕсли;
		
		УстановитьПометкиПодчиненных(Строка, Реквизит);
		
	КонецЦикла;
		
КонецПроцедуры

// Устанавливает состояние пометки у родительских строк строки дерева значений.
// в зависимости от пометки текущей строки.
//
// Параметры:
//  ТекСтрока      - СтрокаДереваЗначений - строка, у которой следует обработать родительские строки.
//  Реквизит       - Строка - имя реквизита, в котором содержится пометка.
// 
Процедура УстановитьПометкиРодителей(ТекСтрока, Реквизит) Экспорт

	Родитель = ТекСтрока.Родитель;
	Если Родитель = Неопределено Тогда
		Возврат;
	КонецЕсли; 

	ТекСостояние       = Родитель[Реквизит];

	НайденыВключенные  = Ложь;
	НайденыВыключенные = Ложь;

	Если Реквизит = "ИспользоватьОтбор" Тогда
		
		Для Каждого Строка Из Родитель.Строки Цикл
			
			Если Строка[Реквизит] = 0 
				И Строка.НастройкиПостроителя <> Неопределено Тогда
				
				НайденыВыключенные = Истина;
				
			ИначеЕсли Строка[Реквизит] = 1 Тогда
				НайденыВключенные  = Истина;
			КонецЕсли; 
			
			Если НайденыВключенные И НайденыВыключенные Тогда
				Прервать;
			КонецЕсли; 
			
		КонецЦикла;
		
	Иначе
		
		Для Каждого Строка Из Родитель.Строки Цикл
			Если Строка[Реквизит] = 0 Тогда
				НайденыВыключенные = Истина;
			ИначеЕсли Строка[Реквизит] = 1
				ИЛИ Строка[Реквизит] = 2 Тогда
				НайденыВключенные  = Истина;
			КонецЕсли; 
			Если НайденыВключенные И НайденыВыключенные Тогда
				Прервать;
			КонецЕсли; 
		КонецЦикла;
		
	КонецЕсли;

	
	Если НайденыВключенные И НайденыВыключенные Тогда
		Включить = 2;
	ИначеЕсли НайденыВключенные И (Не НайденыВыключенные) Тогда
		Включить = 1;
	ИначеЕсли (Не НайденыВключенные) И НайденыВыключенные Тогда
		Включить = 0;
	ИначеЕсли (Не НайденыВключенные) И (Не НайденыВыключенные) Тогда
		Включить = 2;
	КонецЕсли;

	Если Включить = ТекСостояние Тогда
		Возврат;
	Иначе
		Родитель[Реквизит] = Включить;
		УстановитьПометкиРодителей(Родитель, Реквизит);
	КонецЕсли; 
	
КонецПроцедуры

// Составляет полное имя файла из имени каталога и имени файла.
//
// Параметры:
//  ИмяКаталога  - Строка - путь к каталогу файла на диске.
//  ИмяФайла     - Строка - имя файла, без имени каталога.
//
// Возвращаемое значение:
//   Строка - полное имя файла с учетом каталога.
//
Функция ПолучитьИмяФайлаОбмена(ИмяКаталога, ИмяФайла) Экспорт

	Если Не ПустаяСтрока(ИмяФайла) Тогда
		
		Разделитель = ПолучитьРазделительПути();
		Возврат ИмяКаталога + ?(Прав(ИмяКаталога, 1) = Разделитель, "", Разделитель) + ИмяФайла;
		
	Иначе
		
		Возврат ИмяКаталога;
		
	КонецЕсли;

КонецФункции

// Выполняет передачу строки данных для загрузки в базе-приемнике.
//
// Параметры:
//  ИнформацияДляЗаписиВФайл - Строка - строка с данными (текст XML).
//  СтрокаОшибкиВБазеПриемнике - Строка - содержит описание ошибки при загрузке в базе-приемнике.
// 
Процедура ПередатьИнформациюОЗаписиВПриемник(ИнформацияДляЗаписиВФайл, СтрокаОшибкиВБазеПриемнике = "") Экспорт
	
	мОбработкаДляЗагрузкиДанных.ФайлОбмена.УстановитьСтроку(ИнформацияДляЗаписиВФайл);
	
	мОбработкаДляЗагрузкиДанных.ПроизвестиЧтениеДанных(СтрокаОшибкиВБазеПриемнике);
	
	Если Не ПустаяСтрока(СтрокаОшибкиВБазеПриемнике) Тогда
		
		СтрокаСообщения = ПодставитьПараметрыВСтроку(НСтр("ru = 'Загрузка в приемнике: %1'"), СтрокаОшибкиВБазеПриемнике);
		ЗаписатьВПротоколВыполнения(СтрокаСообщения, Неопределено, Истина, , , Истина);
		
	КонецЕсли;
	
КонецПроцедуры

// Выполняет запись имени, типа и значения параметра в фай сообщения обмена для передачи в базу-приемник.
//
// Параметры:
//   Имя                          - Строка - имя параметра.
//   ИсходноеЗначениеПараметра    - Произвольный - значение параметра.
//   ПравилоКонвертации           - Строка - имя правила конвертации для ссылочных типов.
// 
Процедура ПередатьОдинПараметрВПриемник(Имя, ИсходноеЗначениеПараметра, ПравилоКонвертации = "") Экспорт
	
	Если ПустаяСтрока(ПравилоКонвертации) Тогда
		
		УзелПараметра = СоздатьУзел("ЗначениеПараметра");
		
		УстановитьАтрибут(УзелПараметра, "Имя", Имя);
		УстановитьАтрибут(УзелПараметра, "Тип", одТипЗначенияСтрокой(ИсходноеЗначениеПараметра));
		
		ЭтоNULL = Ложь;
		Пусто = одПустое(ИсходноеЗначениеПараметра, ЭтоNULL);
					
		Если Пусто Тогда
			
			// Надо записать что это пустое значение.
			одЗаписатьЭлемент(УзелПараметра, "Пусто");
								
			УзелПараметра.ЗаписатьКонецЭлемента();
			
			ЗаписатьВФайл(УзелПараметра);
			
			Возврат;
								
		КонецЕсли;
	
		одЗаписатьЭлемент(УзелПараметра, "Значение", ИсходноеЗначениеПараметра);
	
		УзелПараметра.ЗаписатьКонецЭлемента();
		
		ЗаписатьВФайл(УзелПараметра);
		
	Иначе
		
		УзелПараметра = СоздатьУзел("ЗначениеПараметра");
		
		УстановитьАтрибут(УзелПараметра, "Имя", Имя);
		
		ЭтоNULL = Ложь;
		Пусто = одПустое(ИсходноеЗначениеПараметра, ЭтоNULL);
					
		Если Пусто Тогда
			
			ПКОСвойств = НайтиПравило(ИсходноеЗначениеПараметра, ПравилоКонвертации);
			ТипПриемника  = ПКОСвойств.Приемник;
			УстановитьАтрибут(УзелПараметра, "Тип", ТипПриемника);
			
			// Надо записать что это пустое значение.
			одЗаписатьЭлемент(УзелПараметра, "Пусто");
								
			УзелПараметра.ЗаписатьКонецЭлемента();
			
			ЗаписатьВФайл(УзелПараметра);
			
			Возврат;
								
		КонецЕсли;
		
		ВыгрузитьДанныеСсылочногоОбъекта(ИсходноеЗначениеПараметра, Неопределено, ПравилоКонвертации, Неопределено, Неопределено, УзелПараметра, Истина);
		
		УзелПараметра.ЗаписатьКонецЭлемента();
		
		ЗаписатьВФайл(УзелПараметра);				
		
	КонецЕсли;	
	
КонецПроцедуры

#КонецОбласти

#Область УстановкаЗначенийРеквизитовИМодальныхПеременныхОбработки

// Возвращает текущее значение версии обработки.
//
// Возвращаемое значение:
//  Строка - текущее значение версии обработки.
//
Функция ВерсияОбъекта() Экспорт
	
	Версия = "1.0.3.376";
	Возврат Версия;
	
КонецФункции

#КонецОбласти

#Область ИнициализацияТаблицПравилОбмена

// Инициализирует колонки таблицы правил конвертации свойств объектов.
//
// Параметры:
//  Таб            - ТаблицаЗначений - инициализируемая таблица правил конвертации свойств.
// 
Процедура ИнициализацияТаблицыПравилКонвертацииСвойств(Таб) Экспорт

	Колонки = Таб.Колонки;

	ДобавитьНедостающиеКолонки(Колонки, "Имя");
	ДобавитьНедостающиеКолонки(Колонки, "Наименование");
	ДобавитьНедостающиеКолонки(Колонки, "Порядок");

	ДобавитьНедостающиеКолонки(Колонки, "ЭтоГруппа", 			одОписаниеТипа("Булево"));
    ДобавитьНедостающиеКолонки(Колонки, "ПравилаГруппы");

	ДобавитьНедостающиеКолонки(Колонки, "ВидИсточника");
	ДобавитьНедостающиеКолонки(Колонки, "ВидПриемника");
	
	ДобавитьНедостающиеКолонки(Колонки, "УпрощеннаяВыгрузкаСвойства", одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "НуженУзелXMLПриВыгрузке", одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "НуженУзелXMLПриВыгрузкеГруппы", одОписаниеТипа("Булево"));

	ДобавитьНедостающиеКолонки(Колонки, "ТипИсточника", одОписаниеТипа("Строка"));
	ДобавитьНедостающиеКолонки(Колонки, "ТипПриемника", одОписаниеТипа("Строка"));
	
	ДобавитьНедостающиеКолонки(Колонки, "Источник");
	ДобавитьНедостающиеКолонки(Колонки, "Приемник");

	ДобавитьНедостающиеКолонки(Колонки, "ПравилоКонвертации");

	ДобавитьНедостающиеКолонки(Колонки, "ПолучитьИзВходящихДанных", одОписаниеТипа("Булево"));
	
	ДобавитьНедостающиеКолонки(Колонки, "НеЗамещать", одОписаниеТипа("Булево"));
	
	ДобавитьНедостающиеКолонки(Колонки, "ПередВыгрузкой");
	ДобавитьНедостающиеКолонки(Колонки, "ПриВыгрузке");
	ДобавитьНедостающиеКолонки(Колонки, "ПослеВыгрузки");

	ДобавитьНедостающиеКолонки(Колонки, "ПередОбработкойВыгрузки");
	ДобавитьНедостающиеКолонки(Колонки, "ПослеОбработкиВыгрузки");

	ДобавитьНедостающиеКолонки(Колонки, "ЕстьОбработчикПередВыгрузкой",			одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ЕстьОбработчикПриВыгрузке",				одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ЕстьОбработчикПослеВыгрузки",				одОписаниеТипа("Булево"));
	
	ДобавитьНедостающиеКолонки(Колонки, "ЕстьОбработчикПередОбработкойВыгрузки",	одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ЕстьОбработчикПослеОбработкиВыгрузки",	одОписаниеТипа("Булево"));
	
	ДобавитьНедостающиеКолонки(Колонки, "ПриводитьКДлине",	одОписаниеТипа("Число"));
	ДобавитьНедостающиеКолонки(Колонки, "ИмяПараметраДляПередачи");
	ДобавитьНедостающиеКолонки(Колонки, "ПоискПоДатеНаРавенство",					одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ВыгружатьГруппуЧерезФайл",					одОписаниеТипа("Булево"));
	
	ДобавитьНедостающиеКолонки(Колонки, "СтрокаПолейПоиска");
	
КонецПроцедуры

#КонецОбласти

#Область ИнициализацияРеквизитовИМодульныхПеременных

// Инициализирует внешнюю обработку с модулем отладки обработчиков событий.
//
// Параметры:
//  РаботаВозможна - Булево - флаг успешной инициализации внешней обработки.
//  ОбъектВладелец - ОбработкаОбъект.УниверсальныйОбменДаннымиXML - объект, который будет являться владельцем 
//                   инициализируемой внешней обработки.
//  
Процедура ИнициализацияВнешнейОбработкиОбработчиковСобытий(РаботаВозможна, ОбъектВладелец) Экспорт
	
	Если Не РаботаВозможна Тогда
		Возврат;
	КонецЕсли; 
	
	Если ФлагРежимОтладкиОбработчиков И ПустаяСтрока(ИмяФайлаВнешнейОбработкиОбработчиковСобытий) Тогда
		
		ЗаписатьВПротоколВыполнения(77); 
		РаботаВозможна = Ложь;
		
	ИначеЕсли ФлагРежимОтладкиОбработчиков Тогда
		
		Попытка
			
			Попытка
				
				Файл = Новый Файл(ИмяФайлаВнешнейОбработкиОбработчиковСобытий);
				Если Файл.Существует() Тогда
					ВнешняяОбработкаОбработчиковСобытий = ВнешниеОбработки.Создать(ИмяФайлаВнешнейОбработкиОбработчиковСобытий);
				Иначе
					ВнешняяОбработкаОбработчиковСобытий = Обработки[ИмяФайлаВнешнейОбработкиОбработчиковСобытий].Создать();
				КонецЕсли;
				
			Исключение
				
				ВызватьИсключение
					НСтр("ru = 'Ошибка при подключении внешней обработки отладки.'");
				
			КонецПопытки;
			
			ВнешняяОбработкаОбработчиковСобытий.Конструктор(ОбъектВладелец);
			
		Исключение
			
			ДеструкторВнешнейОбработкиОбработчиковСобытий();
			
			СообщитьПользователю(ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
			ЗаписатьВПротоколВыполнения(78);
			
			РаботаВозможна               = Ложь;
			ФлагРежимОтладкиОбработчиков = Ложь;
			
		КонецПопытки;
		
	КонецЕсли;
	
	Если РаботаВозможна Тогда
		
		ОбщиеПроцедурыФункции = ЭтотОбъект;
		
	КонецЕсли; 
	
КонецПроцедуры

// Деструктор внешней обработки.
//
// Параметры:
//  ВключенРежимОтладки - Булево - признак включения режима отладки.
//  
Процедура ДеструкторВнешнейОбработкиОбработчиковСобытий(ВключенРежимОтладки = Ложь) Экспорт
	
	Если Не ВключенРежимОтладки Тогда
		
		Если ВнешняяОбработкаОбработчиковСобытий <> Неопределено Тогда
			
			Попытка
				
				ВнешняяОбработкаОбработчиковСобытий.Деструктор();
				
			Исключение
				СообщитьПользователю(ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
			КонецПопытки; 
			
		КонецЕсли; 
		
		ВнешняяОбработкаОбработчиковСобытий = Неопределено;
		ОбщиеПроцедурыФункции               = Неопределено;
		
	КонецЕсли;
	
КонецПроцедуры

// Удаляет временные файлы с заданным именем.
//
// Параметры:
//  ИмяВременногоФайла - Строка - полное имя удаляемого файла. После выполнения процедуры очищается.
//  
Процедура УдалитьВременныеФайлы(ИмяВременногоФайла) Экспорт
	
	Если Не ПустаяСтрока(ИмяВременногоФайла) Тогда
		
		Попытка
			
			УдалитьФайлы(ИмяВременногоФайла);
			
			ИмяВременногоФайла = "";
			
		Исключение
			ЗаписьЖурналаРегистрации(НСтр("ru = 'Универсальный обмен данными в формате XML'", КодОсновногоЯзыка()),
				УровеньЖурналаРегистрации.Ошибка,,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		КонецПопытки;
		
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

#Область ПроцедурыИФункцииРаботыСФайломОбмена

// Открывает файл обмена, записывает заголовок файла в соответствии с форматом обмена.
//
// Параметры:
//  Нет.
//
Функция ОткрытьФайлВыгрузки(СтрокаСообщенияОбОшибке = "")

	// Архивные файлы будем идентифицировать по расширению ".zip".
	
	Если АрхивироватьФайл Тогда
		ИмяФайлаОбмена = СтрЗаменить(ИмяФайлаОбмена, ".zip", ".xml");
	КонецЕсли;
    	
	ФайлОбмена = Новый ЗаписьТекста;
	Попытка
		
		Если НепосредственноеЧтениеВИБПриемнике Тогда
			ФайлОбмена.Открыть(ПолучитьИмяВременногоФайла(".xml"), КодировкаТекста.UTF8);
		Иначе
			ФайлОбмена.Открыть(ИмяФайлаОбмена, КодировкаТекста.UTF8);
		КонецЕсли;
				
	Исключение
		
		СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(8);
		Возврат "";
		
	КонецПопытки; 
	
	СтрокаИнформацииОXML = "<?xml version=""1.0"" encoding=""UTF-8""?>";
	
	ФайлОбмена.ЗаписатьСтроку(СтрокаИнформацииОXML);

	ВременныйЗаписьXML = Новый ЗаписьXML();
	
	ВременныйЗаписьXML.УстановитьСтроку();
	
	ВременныйЗаписьXML.ЗаписатьНачалоЭлемента("ФайлОбмена");
							
	УстановитьАтрибут(ВременныйЗаписьXML, "ВерсияФормата", "2.0");
	УстановитьАтрибут(ВременныйЗаписьXML, "ДатаВыгрузки",				ТекущаяДатаСеанса());
	УстановитьАтрибут(ВременныйЗаписьXML, "НачалоПериодаВыгрузки",		ДатаНачала);
	УстановитьАтрибут(ВременныйЗаписьXML, "ОкончаниеПериодаВыгрузки",	ДатаОкончания);
	УстановитьАтрибут(ВременныйЗаписьXML, "ИмяКонфигурацииИсточника",	Конвертация().Источник);
	УстановитьАтрибут(ВременныйЗаписьXML, "ИмяКонфигурацииПриемника",	Конвертация().Приемник);
	УстановитьАтрибут(ВременныйЗаписьXML, "ИдПравилКонвертации",		Конвертация().Ид);
	УстановитьАтрибут(ВременныйЗаписьXML, "Комментарий",				Комментарий);
	
	ВременныйЗаписьXML.ЗаписатьКонецЭлемента();
	
	Стр = ВременныйЗаписьXML.Закрыть(); 
	
	Стр = СтрЗаменить(Стр, "/>", ">");
	
	ФайлОбмена.ЗаписатьСтроку(Стр);
	
	Возврат СтрокаИнформацииОXML + Символы.ПС + Стр;
			
КонецФункции

// Закрывает файл обмена
//
// Параметры:
//  Нет.
//
Процедура ЗакрытьФайл()

    ФайлОбмена.ЗаписатьСтроку("</ФайлОбмена>");
	ФайлОбмена.Закрыть();
	
КонецПроцедуры

#КонецОбласти

#Область ПроцедурыИФункцииРаботыСВременнымиФайлами

Функция ЗаписьТекстаВоВременныйФайл(СписокВременныхФайлов)
	
	ИмяФайлаЗаписей = ПолучитьИмяВременногоФайла();
	
	ВременныйФайлЗаписей = Новый ЗаписьТекста;
	
	Если БезопасныйРежим() <> Ложь Тогда
		УстановитьОтключениеБезопасногоРежима(Истина);
	КонецЕсли;
	
	Попытка
		ВременныйФайлЗаписей.Открыть(ИмяФайлаЗаписей, КодировкаТекста.UTF8);
	Исключение
		ЗаписатьИнформациюОбОшибкеОбработчикиКонвертации(1000,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
			НСтр("ru = 'Ошибка при создании временного файла для выгрузки данных'"));
		ВызватьИсключение;
	КонецПопытки;
	
	// Удаление временных файлов происходит не по месту,
	// с помощью УдалитьФайлы(ИмяФайлаЗаписей), а централизованно.
	СписокВременныхФайлов.Добавить(ИмяФайлаЗаписей);
		
	Возврат ВременныйФайлЗаписей;
	
КонецФункции

Функция ЧтениеТекстаИзВременногоФайла(ИмяВременногоФайла)
	
	ВременныйФайл = Новый ЧтениеТекста;
	
	Если БезопасныйРежим() <> Ложь Тогда
		УстановитьОтключениеБезопасногоРежима(Истина);
	КонецЕсли;
	
	Попытка
		ВременныйФайл.Открыть(ИмяВременногоФайла, КодировкаТекста.UTF8);
	Исключение
		ЗаписатьИнформациюОбОшибкеОбработчикиКонвертации(1000,
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
			НСтр("ru = 'Ошибка при открытии временного файла для переноса данных в файл обмена'"));
		ВызватьИсключение;
	КонецПопытки;
	
	Возврат ВременныйФайл;
КонецФункции

Процедура ПеренестиДанныеИзВременныхФайлов(СписокВременныхФайлов)
	
	Для Каждого ИмяВременногоФайла Из СписокВременныхФайлов Цикл
		ВременныйФайл = ЧтениеТекстаИзВременногоФайла(ИмяВременногоФайла);
		
		СтрокаВременногоФайла = ВременныйФайл.ПрочитатьСтроку();
		Пока СтрокаВременногоФайла <> Неопределено Цикл
			ЗаписатьВФайл(СтрокаВременногоФайла);	
			СтрокаВременногоФайла = ВременныйФайл.ПрочитатьСтроку();
		КонецЦикла;
		
		ВременныйФайл.Закрыть();
	КонецЦикла;
	
	Если БезопасныйРежим() <> Ложь Тогда
		УстановитьОтключениеБезопасногоРежима(Истина);
	КонецЕсли;
	
	Для Каждого ИмяВременногоФайла Из СписокВременныхФайлов Цикл
		УдалитьФайлы(ИмяВременногоФайла);
	КонецЦикла;
	
КонецПроцедуры

#КонецОбласти

#Область ПроцедурыИФункцииРаботыСПротоколомОбмена

// Выполняет инициализацию файла для записи событий загрузки/выгрузки данных.
//
// Параметры:
//  Нет.
// 
Процедура ИнициализироватьВедениеПротоколаОбмена() Экспорт
	
	Если ПустаяСтрока(ИмяФайлаПротоколаОбмена) Тогда
		
		мФайлПротоколаДанных = Неопределено;
		ФлагКомментироватьОбработкуОбъектов = ВыводВОкноСообщенийИнформационныхСообщений;		
		Возврат;
		
	Иначе	
		
		ФлагКомментироватьОбработкуОбъектов = ВыводВПротоколИнформационныхСообщений ИЛИ ВыводВОкноСообщенийИнформационныхСообщений;		
		
	КонецЕсли;
	
	мФайлПротоколаДанных = Новый ЗаписьТекста(ИмяФайлаПротоколаОбмена, КодировкаФайлаПротоколаОбмена(), , ДописыватьДанныеВПротоколОбмена) ;
	
КонецПроцедуры

Процедура ИнициализироватьВедениеПротоколаОбменаДляЭкспортаОбработчиков()
	
	ИмяВременногоФайлаПротоколаОбмена = ПолучитьНовоеУникальноеИмяВременногоФайла(ИмяВременногоФайлаПротоколаОбмена);
	
	мФайлПротоколаДанных = Новый ЗаписьТекста(ИмяВременногоФайлаПротоколаОбмена, КодировкаФайлаПротоколаОбмена());
	
	ФлагКомментироватьОбработкуОбъектов = Ложь;
	
КонецПроцедуры

Функция КодировкаФайлаПротоколаОбмена()
	
	ПредставлениеКодировки = СокрЛП(КодировкаФайлаПротоколаОбмена);
	
	Результат = КодировкаТекста.ANSI;
	Если Не ПустаяСтрока(КодировкаФайлаПротоколаОбмена) Тогда
		Если СтрНачинаетсяС(ПредставлениеКодировки, "КодировкаТекста.") Тогда
			ПредставлениеКодировки = СтрЗаменить(ПредставлениеКодировки, "КодировкаТекста.", "");
			Попытка
				Результат = КодировкаТекста[ПредставлениеКодировки];
			Исключение
				ТекстОшибки = ПодставитьПараметрыВСтроку(НСтр("ru = 'Неизвестная кодировка файла протокола обмена: %1.
				|Используется ANSI.'"), ПредставлениеКодировки);
				ЗаписьЖурналаРегистрации(НСтр("ru = 'Универсальный обмен данными в формате XML'", КодОсновногоЯзыка()),
					УровеньЖурналаРегистрации.Предупреждение, , , ТекстОшибки);
			КонецПопытки;
		Иначе
			Результат = ПредставлениеКодировки;
		КонецЕсли;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Закрывает файл протокола обмена данными. Файл сохраняется на диск.
//
Процедура ЗавершитьВедениеПротоколаОбмена() Экспорт 
	
	Если мФайлПротоколаДанных <> Неопределено Тогда
		
		мФайлПротоколаДанных.Закрыть();
				
	КонецЕсли;	
	
	мФайлПротоколаДанных = Неопределено;
	
КонецПроцедуры

// Сохраняет в протокол выполнения (или выводит на экран) сообщения указанной структуры.
//
// Параметры:
//  Код               - Число - код сообщения.
//  СтруктураЗаписи   - Структура - структура записи протокола.
//  ВзвестиФлагОшибок - Булево - если истина, то - это сообщение об ошибке. Взводится ФлагОшибки.
// 
Функция ЗаписатьВПротоколВыполнения(Код="", СтруктураЗаписи=Неопределено, ВзвестиФлагОшибок=Истина, 
	Уровень=0, Выравнивание=22, БезусловнаяЗаписьВПротоколОбмена = Ложь) Экспорт

	Отступ = "";
    Для Сч = 0 По Уровень-1 Цикл
		Отступ = Отступ + Символы.Таб;
	КонецЦикла; 
	
	Если ТипЗнч(Код) = одТипЧисло Тогда
		
		Если одСообщения = Неопределено Тогда
			ИнициализацияСообщений();
		КонецЕсли;
		
		Стр = одСообщения[Код];
		
	Иначе
		
		Стр = Строка(Код);
		
	КонецЕсли;

	Стр = Отступ + Стр;
	
	Если СтруктураЗаписи <> Неопределено Тогда
		
		Для каждого Поле Из СтруктураЗаписи Цикл
			
			Значение = Поле.Значение;
			Если Значение = Неопределено Тогда
				Продолжить;
			КонецЕсли; 
			Ключ = Поле.Ключ;
			Стр  = Стр + Символы.ПС + Отступ + Символы.Таб + одДополнитьСтроку(Ключ, Выравнивание) + " =  " + Строка(Значение);
			
		КонецЦикла;
		
	КонецЕсли;
	
	ИтоговаяСтрокаДляЗаписи = Символы.ПС + Стр;

	
	Если ВзвестиФлагОшибок Тогда
		
		УстановитьФлагОшибки(Истина);
		СообщитьПользователю(ИтоговаяСтрокаДляЗаписи);
		
	Иначе
		
		Если НеВыводитьНикакихИнформационныхСообщенийПользователю = Ложь
			И (БезусловнаяЗаписьВПротоколОбмена ИЛИ ВыводВОкноСообщенийИнформационныхСообщений) Тогда
			
			СообщитьПользователю(ИтоговаяСтрокаДляЗаписи);
			
		КонецЕсли;
		
	КонецЕсли;
	
	Если мФайлПротоколаДанных <> Неопределено Тогда
		
		Если ВзвестиФлагОшибок Тогда
			
			мФайлПротоколаДанных.ЗаписатьСтроку(Символы.ПС + "Ошибка.");
			
		КонецЕсли;
		
		Если ВзвестиФлагОшибок ИЛИ БезусловнаяЗаписьВПротоколОбмена ИЛИ ВыводВПротоколИнформационныхСообщений Тогда
			
			мФайлПротоколаДанных.ЗаписатьСтроку(ИтоговаяСтрокаДляЗаписи);
		
		КонецЕсли;		
		
	КонецЕсли;
	
	Возврат Стр;
		
КонецФункции

// Записывает информацию об ошибке в протокол выполнения обмена для обработчика очистки данных.
//
Процедура ЗаписатьИнформациюОбОшибкеОбработчикаОчисткиДанных(КодСообщения, СтрокаОшибки, ИмяПравилаОчисткиДанных, Объект = "", ИмяОбработчика = "")
	
	ЗП                        = ПолучитьСтруктуруЗаписиПротокола(КодСообщения, СтрокаОшибки);
	ЗП.ПОД                    = ИмяПравилаОчисткиДанных;
	
	Если Объект <> "" Тогда
		ОписаниеТипов = Новый ОписаниеТипов("Строка");
		ОбъектСтрока  = ОписаниеТипов.ПривестиЗначение(Объект);
		Если Не ПустаяСтрока(ОбъектСтрока) Тогда
			ЗП.Объект = ОбъектСтрока + "  (" + ТипЗнч(Объект) + ")";
		Иначе
			ЗП.Объект = "" + ТипЗнч(Объект) + "";
		КонецЕсли;
	КонецЕсли;
	
	Если ИмяОбработчика <> "" Тогда
		ЗП.Обработчик             = ИмяОбработчика;
	КонецЕсли;
	
	СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(КодСообщения, ЗП);
	
	Если Не ФлагРежимОтладки Тогда
		ВызватьИсключение СтрокаСообщенияОбОшибке;
	КонецЕсли;	
	
КонецПроцедуры

// Регистрирует в протоколе выполнения ошибку обработчика ПКО (выгрузка).
//
Процедура ЗаписатьИнформациюОбОшибкеВыгрузкиОбработчикаПКО(КодСообщения, СтрокаОшибки, ПКО, Источник, ИмяОбработчика)
	
	ЗП                        = ПолучитьСтруктуруЗаписиПротокола(КодСообщения, СтрокаОшибки);
	ЗП.ПКО                    = ПКО.Имя + "  (" + ПКО.Наименование + ")";
	
	ОписаниеТипов = Новый ОписаниеТипов("Строка");
	ИсточникСтрока  = ОписаниеТипов.ПривестиЗначение(Источник);
	Если Не ПустаяСтрока(ИсточникСтрока) Тогда
		ЗП.Объект = ИсточникСтрока + "  (" + ТипЗнч(Источник) + ")";
	Иначе
		ЗП.Объект = "(" + ТипЗнч(Источник) + ")";
	КонецЕсли;
	
	ЗП.Обработчик = ИмяОбработчика;
	
	СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(КодСообщения, ЗП);
	
	Если Не ФлагРежимОтладки Тогда
		ВызватьИсключение СтрокаСообщенияОбОшибке;
	КонецЕсли;
		
КонецПроцедуры

Процедура ЗаписатьИнформациюОбОшибкеОбработчикиПВД(КодСообщения, СтрокаОшибки, ИмяПравила, ИмяОбработчика, Объект = Неопределено)
	
	ЗП                        = ПолучитьСтруктуруЗаписиПротокола(КодСообщения, СтрокаОшибки);
	ЗП.ПВД                    = ИмяПравила;
	
	Если Объект <> Неопределено Тогда
		ОписаниеТипов = Новый ОписаниеТипов("Строка");
		ОбъектСтрока  = ОписаниеТипов.ПривестиЗначение(Объект);
		Если Не ПустаяСтрока(ОбъектСтрока) Тогда
			ЗП.Объект = ОбъектСтрока + "  (" + ТипЗнч(Объект) + ")";
		Иначе
			ЗП.Объект = "" + ТипЗнч(Объект) + "";
		КонецЕсли;
	КонецЕсли;
	
	ЗП.Обработчик             = ИмяОбработчика;
	
	СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(КодСообщения, ЗП);
	
	Если Не ФлагРежимОтладки Тогда
		ВызватьИсключение СтрокаСообщенияОбОшибке;
	КонецЕсли;
	
КонецПроцедуры

Функция ЗаписатьИнформациюОбОшибкеОбработчикиКонвертации(КодСообщения, СтрокаОшибки, ИмяОбработчика)
	
	ЗП                        = ПолучитьСтруктуруЗаписиПротокола(КодСообщения, СтрокаОшибки);
	ЗП.Обработчик             = ИмяОбработчика;
	СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(КодСообщения, ЗП);
	Возврат СтрокаСообщенияОбОшибке;
	
КонецФункции

#КонецОбласти

#Область ОписаниеТиповКоллекций

// Возвращаемое значение:
//   ТаблицаЗначений - коллекция правил конвертации данных:
//     * Имя - Строка
//     * Наименование - Строка
//     * Порядок - Число
//     * СинхронизироватьПоИдентификатору - Булево
//     * НеСоздаватьЕслиНеНайден - Булево
//     * НеВыгружатьОбъектыСвойствПоСсылкам - Булево
//     * ПродолжитьПоискПоПолямПоискаЕслиПоИдентификаторуНеНашли - Булево
//     * ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD - Булево
//     * ИспользоватьБыстрыйПоискПриЗагрузке - Булево
//     * ГенерироватьНовыйНомерИлиКодЕслиНеУказан - Булево
//     * МаленькоеКоличествоОбъектов - Булево
//     * КоличествоОбращенийДляВыгрузкиСсылки - Число
//     * КоличествоЭлементовВИБ - Число
//     * СпособВыгрузки - Произвольный
//     * Источник - Произвольный
//     * Приемник - Произвольный
//     * ТипИсточника - Строка
//     * ПередВыгрузкой - Произвольный
//     * ПриВыгрузке - Произвольный
//     * ПослеВыгрузки - Произвольный
//     * ПослеВыгрузкиВФайл - Произвольный
//     * ЕстьОбработчикПередВыгрузкой - Булево
//     * ЕстьОбработчикПриВыгрузке - Булево
//     * ЕстьОбработчикПослеВыгрузки - Булево
//     * ЕстьОбработчикПослеВыгрузкиВФайл - Булево
//     * ПередЗагрузкой - Произвольный
//     * ПриЗагрузке - Произвольный
//     * ПослеЗагрузки - Произвольный
//     * ПоследовательностьПолейПоиска - Произвольный
//     * ПоискПоТабличнымЧастям - см. КоллекцияПоискПоТабличнымЧастям
//     * ЕстьОбработчикПередЗагрузкой - Булево
//     * ЕстьОбработчикПриЗагрузке - Булево
//     * ЕстьОбработчикПослеЗагрузки - Булево
//     * ЕстьОбработчикПоследовательностьПолейПоиска - Булево
//     * СвойстваПоиска - см. КоллекцияПравилаКонвертацииСвойств
//     * Свойства - см. КоллекцияПравилаКонвертацииСвойств
//     * Выгруженные - ТаблицаЗначений
//     * ВыгружатьПредставлениеИсточника - Булево
//     * НеЗамещать - Булево
//     * ЗапоминатьВыгруженные - Булево
//     * ВсеОбъектыВыгружены - Булево
// 
Функция КоллекцияПравилаКонвертации()
	
	Возврат ТаблицаПравилКонвертации;
	
КонецФункции

// Возвращаемое значение:
//   ДеревоЗначений - коллекция правил выгрузки данных:
//     * Включить - Число
//     * ЭтоГруппа - Булево
//     * Имя - Строка
//     * Наименование - Строка
//     * Порядок - Число
//     * СпособОтбораДанных - Произвольный
//     * ОбъектВыборки - Произвольный
//     * ПравилоКонвертации - Произвольный
//     * ПередОбработкой - Строка
//     * ПослеОбработки - Строка
//     * ПередВыгрузкой - Строка
//     * ПослеВыгрузки - Строка
//     * ИспользоватьОтбор - Булево
//     * НастройкиПостроителя - Произвольный
//     * ИмяОбъектаДляЗапроса - Строка
//     * ИмяОбъектаДляЗапросаРегистра - Строка
//     * ВыбиратьДанныеДляВыгрузкиОднимЗапросом - Булево
//     * СсылкаНаУзелОбмена - ПланОбменаСсылка
//
Функция КоллекцияПравилаВыгрузки()
	
	Возврат ТаблицаПравилВыгрузки;
	
КонецФункции

// Возвращаемое значение:
//   ТаблицаЗначений - коллекция правил поиска по табличным частям:
//     * ИмяЭлемента - Произвольный
//     * ПоляПоискаТЧ - Массив из Произвольный
// 
Функция КоллекцияПоискПоТабличнымЧастям()
	
	ПоискПоТабличнымЧастям = Новый ТаблицаЗначений;
	ПоискПоТабличнымЧастям.Колонки.Добавить("ИмяЭлемента");
	ПоискПоТабличнымЧастям.Колонки.Добавить("ПоляПоискаТЧ");
	
	Возврат ПоискПоТабличнымЧастям;
	
КонецФункции

// Возвращаемое значение:
//   ТаблицаЗначений - коллекция правил конвертации свойств данных:
//     * Имя - Строка
//     * Наименование - Строка
//     * Порядок - Число
//     * ЭтоГруппа - Булево
//     * ЭтоПолеПоиска - Булево
//     * ПравилаГруппы - см. КоллекцияПравилаКонвертацииСвойств
//     * ПравилаГруппыОтключенные - Произвольный
//     * ВидИсточника - Произвольный
//     * ВидПриемника - Произвольный
//     * УпрощеннаяВыгрузкаСвойства - Булево
//     * НуженУзелXMLПриВыгрузке - Булево
//     * НуженУзелXMLПриВыгрузкеГруппы - Булево
//     * ТипИсточника - Строка
//     * ТипПриемника - Строка
//     * Источник - Произвольный
//     * Приемник - Произвольный
//     * ПравилоКонвертации - Произвольный
//     * ПолучитьИзВходящихДанных - Булево
//     * НеЗамещать - Булево
//     * ЭтоОбязательноеСвойство - Булево
//     * ПередВыгрузкой - Произвольный
//     * ИмяОбработчикаПередВыгрузкой - Произвольный
//     * ПриВыгрузке - Произвольный
//     * ИмяОбработчикаПриВыгрузке - Произвольный
//     * ПослеВыгрузки - Произвольный
//     * ИмяОбработчикаПослеВыгрузки - Произвольный
//     * ПередОбработкойВыгрузки - Произвольный
//     * ИмяОбработчикаПередОбработкойВыгрузки - Произвольный
//     * ПослеОбработкиВыгрузки - Произвольный
//     * ИмяОбработчикаПослеОбработкиВыгрузки - Произвольный
//     * ЕстьОбработчикПередВыгрузкой - Булево
//     * ЕстьОбработчикПриВыгрузке - Булево
//     * ЕстьОбработчикПослеВыгрузки - Булево
//     * ЕстьОбработчикПередОбработкойВыгрузки - Булево
//     * ЕстьОбработчикПослеОбработкиВыгрузки - Булево
//     * ПриводитьКДлине - Число
//     * ИмяПараметраДляПередачи - Строка
//     * ПоискПоДатеНаРавенство - Булево
//     * ВыгружатьГруппуЧерезФайл - Булево
//     * СтрокаПолейПоиска - Произвольный
// 
Функция КоллекцияПравилаКонвертацииСвойств()
	
	Возврат мТаблицаПравилКонвертацииСвойств;
	
КонецФункции

// Возвращаемое значение:
//   ТаблицаЗначений:
//     * Ссылка - ЛюбаяСсылка - ссылка на выгружаемый объект.
//
Функция КоллекцияСтекВызововВыгрузкиДанных()
	
	Возврат мСтекВызововВыгрузкиДанных;
	
КонецФункции

// Возвращаемое значение:
//   Структура:
//     * ТаблицаПравилВыгрузки - см. КоллекцияПравилаВыгрузки
//     * ТаблицаПравилКонвертации - см. КоллекцияПравилаКонвертации
//     * Алгоритмы - Структура
//     * Запросы - Структура
//     * Конвертация - Произвольный
//     * мXMLПравила - Произвольный
//     * ТаблицаНастройкиПараметров - ТаблицаЗначений
//     * Параметры - Структура
//     * ВерсияПлатформыПриемника - Строка
//
Функция ОписаниеСтруктурыПравил()
	
	СтруктураПравил = Новый Структура;

	СтруктураПравил.Вставить("ТаблицаПравилВыгрузки");
	СтруктураПравил.Вставить("ТаблицаПравилКонвертации");
	СтруктураПравил.Вставить("Алгоритмы");
	СтруктураПравил.Вставить("Запросы");
	СтруктураПравил.Вставить("Конвертация");
	СтруктураПравил.Вставить("мXMLПравила");
	СтруктураПравил.Вставить("ТаблицаНастройкиПараметров");
	СтруктураПравил.Вставить("Параметры");
	
	СтруктураПравил.Вставить("ВерсияПлатформыПриемника");
	
	Возврат СтруктураПравил;
	
КонецФункции

#КонецОбласти

#Область ПроцедурыЗагрузкиПравилОбмена

// Осуществляет загрузку правила конвертации группы свойств.
//
// Параметры:
//   ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//   ТаблицаСвойств - см. КоллекцияПравилаКонвертацииСвойств
//
Процедура ЗагрузитьПКГС(ПравилаОбмена, ТаблицаСвойств)

	Если одАтрибут(ПравилаОбмена, одТипБулево, "Отключить") Тогда
		одПропустить(ПравилаОбмена);
		Возврат;
	КонецЕсли;
	
	НоваяСтрока               = ТаблицаСвойств.Добавить();
	НоваяСтрока.ЭтоГруппа     = Истина;
	НоваяСтрока.ПравилаГруппы = КоллекцияПравилаКонвертацииСвойств().Скопировать();
	
	// Значения по умолчанию

	НоваяСтрока.НеЗамещать               = Ложь;
	НоваяСтрока.ПолучитьИзВходящихДанных = Ложь;
	НоваяСтрока.УпрощеннаяВыгрузкаСвойства = Ложь;
	
	СтрокаПолейПоиска = "";	
	
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		Если      ИмяУзла = "Источник" Тогда
			НоваяСтрока.Источник		= одАтрибут(ПравилаОбмена, одТипСтрока, "Имя");
			НоваяСтрока.ВидИсточника	= одАтрибут(ПравилаОбмена, одТипСтрока, "Вид");
			НоваяСтрока.ТипИсточника	= одАтрибут(ПравилаОбмена, одТипСтрока, "Тип");
			одПропустить(ПравилаОбмена);
			
		ИначеЕсли ИмяУзла = "Приемник" Тогда
			НоваяСтрока.Приемник		= одАтрибут(ПравилаОбмена, одТипСтрока, "Имя");
			НоваяСтрока.ВидПриемника	= одАтрибут(ПравилаОбмена, одТипСтрока, "Вид");
			НоваяСтрока.ТипПриемника	= одАтрибут(ПравилаОбмена, одТипСтрока, "Тип");
			одПропустить(ПравилаОбмена);
			
		ИначеЕсли ИмяУзла = "Свойство" Тогда
			ЗагрузитьПКС(ПравилаОбмена, НоваяСтрока.ПравилаГруппы, , СтрокаПолейПоиска);

		ИначеЕсли ИмяУзла = "ПередОбработкойВыгрузки" Тогда
			НоваяСтрока.ПередОбработкойВыгрузки	= ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			НоваяСтрока.ЕстьОбработчикПередОбработкойВыгрузки = Не ПустаяСтрока(НоваяСтрока.ПередОбработкойВыгрузки);
			
		ИначеЕсли ИмяУзла = "ПослеОбработкиВыгрузки" Тогда
			НоваяСтрока.ПослеОбработкиВыгрузки	= ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			НоваяСтрока.ЕстьОбработчикПослеОбработкиВыгрузки = Не ПустаяСтрока(НоваяСтрока.ПослеОбработкиВыгрузки);
			
		ИначеЕсли ИмяУзла = "Код" Тогда
			НоваяСтрока.Имя = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			
		ИначеЕсли ИмяУзла = "Наименование" Тогда
			НоваяСтрока.Наименование = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			
		ИначеЕсли ИмяУзла = "Порядок" Тогда
			НоваяСтрока.Порядок = одЗначениеЭлемента(ПравилаОбмена, одТипЧисло);
			
		ИначеЕсли ИмяУзла = "НеЗамещать" Тогда
			НоваяСтрока.НеЗамещать = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);
			
		ИначеЕсли ИмяУзла = "КодПравилаКонвертации" Тогда
			НоваяСтрока.ПравилоКонвертации = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			
		ИначеЕсли ИмяУзла = "ПередВыгрузкой" Тогда
			НоваяСтрока.ПередВыгрузкой = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			НоваяСтрока.ЕстьОбработчикПередВыгрузкой = Не ПустаяСтрока(НоваяСтрока.ПередВыгрузкой);
			
		ИначеЕсли ИмяУзла = "ПриВыгрузке" Тогда
			НоваяСтрока.ПриВыгрузке = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			НоваяСтрока.ЕстьОбработчикПриВыгрузке    = Не ПустаяСтрока(НоваяСтрока.ПриВыгрузке);
			
		ИначеЕсли ИмяУзла = "ПослеВыгрузки" Тогда
			НоваяСтрока.ПослеВыгрузки = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
	        НоваяСтрока.ЕстьОбработчикПослеВыгрузки  = Не ПустаяСтрока(НоваяСтрока.ПослеВыгрузки);
			
		ИначеЕсли ИмяУзла = "ВыгружатьГруппуЧерезФайл" Тогда
			НоваяСтрока.ВыгружатьГруппуЧерезФайл = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);
			
		ИначеЕсли ИмяУзла = "ПолучитьИзВходящихДанных" Тогда
			НоваяСтрока.ПолучитьИзВходящихДанных = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);
			
		ИначеЕсли (ИмяУзла = "Группа") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		КонецЕсли;
		
	КонецЦикла;
	
	НоваяСтрока.СтрокаПолейПоиска = СтрокаПолейПоиска;
	
	НоваяСтрока.НуженУзелXMLПриВыгрузке = НоваяСтрока.ЕстьОбработчикПриВыгрузке ИЛИ НоваяСтрока.ЕстьОбработчикПослеВыгрузки;
	
	НоваяСтрока.НуженУзелXMLПриВыгрузкеГруппы = НоваяСтрока.ЕстьОбработчикПослеОбработкиВыгрузки; 

КонецПроцедуры

Процедура ДобавитьПолеКСтрокеПоиска(СтрокаПолейПоиска, ИмяПоля)
	
	Если ПустаяСтрока(ИмяПоля) Тогда
		Возврат;
	КонецЕсли;
	
	Если НЕ ПустаяСтрока(СтрокаПолейПоиска) Тогда
		СтрокаПолейПоиска = СтрокаПолейПоиска + ",";
	КонецЕсли;
	
	СтрокаПолейПоиска = СтрокаПолейПоиска + ИмяПоля;
	
КонецПроцедуры

// Осуществляет загрузку правила конвертации свойств.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект, содержащий текст правил обмена.
//  ТаблицаСвойств - см. КоллекцияПравилаКонвертацииСвойств
//  ТаблицаПоиска - см. КоллекцияПравилаКонвертацииСвойств
//
Процедура ЗагрузитьПКС(ПравилаОбмена, ТаблицаСвойств, ТаблицаПоиска = Неопределено, СтрокаПолейПоиска = "")

	Если одАтрибут(ПравилаОбмена, одТипБулево, "Отключить") Тогда
		одПропустить(ПравилаОбмена);
		Возврат;
	КонецЕсли;

	
	ЭтоПолеПоиска = одАтрибут(ПравилаОбмена, одТипБулево, "Поиск");
	
	Если ЭтоПолеПоиска 
		И ТаблицаПоиска <> Неопределено Тогда
		
		НоваяСтрока = ТаблицаПоиска.Добавить();
		
	Иначе
		
		НоваяСтрока = ТаблицаСвойств.Добавить();
		
	КонецЕсли;  

	
	// Значения по умолчанию

	НоваяСтрока.НеЗамещать               = Ложь;
	НоваяСтрока.ПолучитьИзВходящихДанных = Ложь;
	
	
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		Если ИмяУзла = "Источник" Тогда
			НоваяСтрока.Источник		= одАтрибут(ПравилаОбмена, одТипСтрока, "Имя");
			НоваяСтрока.ВидИсточника	= одАтрибут(ПравилаОбмена, одТипСтрока, "Вид");
			НоваяСтрока.ТипИсточника	= одАтрибут(ПравилаОбмена, одТипСтрока, "Тип");
			одПропустить(ПравилаОбмена);
			
		ИначеЕсли ИмяУзла = "Приемник" Тогда
			НоваяСтрока.Приемник		= одАтрибут(ПравилаОбмена, одТипСтрока, "Имя");
			НоваяСтрока.ВидПриемника	= одАтрибут(ПравилаОбмена, одТипСтрока, "Вид");
			НоваяСтрока.ТипПриемника	= одАтрибут(ПравилаОбмена, одТипСтрока, "Тип");
			
			Если ЭтоПолеПоиска Тогда
				ДобавитьПолеКСтрокеПоиска(СтрокаПолейПоиска, НоваяСтрока.Приемник);
			КонецЕсли;
			
			одПропустить(ПравилаОбмена);
			
		ИначеЕсли ИмяУзла = "Код" Тогда
			НоваяСтрока.Имя = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			
		ИначеЕсли ИмяУзла = "Наименование" Тогда
			НоваяСтрока.Наименование = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			
		ИначеЕсли ИмяУзла = "Порядок" Тогда
			НоваяСтрока.Порядок = одЗначениеЭлемента(ПравилаОбмена, одТипЧисло);
			
		ИначеЕсли ИмяУзла = "НеЗамещать" Тогда
			НоваяСтрока.НеЗамещать = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);
			
		ИначеЕсли ИмяУзла = "КодПравилаКонвертации" Тогда
			НоваяСтрока.ПравилоКонвертации = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			
		ИначеЕсли ИмяУзла = "ПередВыгрузкой" Тогда
			НоваяСтрока.ПередВыгрузкой = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			НоваяСтрока.ЕстьОбработчикПередВыгрузкой = Не ПустаяСтрока(НоваяСтрока.ПередВыгрузкой);
			
		ИначеЕсли ИмяУзла = "ПриВыгрузке" Тогда
			НоваяСтрока.ПриВыгрузке = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			НоваяСтрока.ЕстьОбработчикПриВыгрузке    = Не ПустаяСтрока(НоваяСтрока.ПриВыгрузке);
			
		ИначеЕсли ИмяУзла = "ПослеВыгрузки" Тогда
			НоваяСтрока.ПослеВыгрузки = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
	        НоваяСтрока.ЕстьОбработчикПослеВыгрузки  = Не ПустаяСтрока(НоваяСтрока.ПослеВыгрузки);
			
		ИначеЕсли ИмяУзла = "ПолучитьИзВходящихДанных" Тогда
			НоваяСтрока.ПолучитьИзВходящихДанных = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);
			
		ИначеЕсли ИмяУзла = "ПриводитьКДлине" Тогда
			НоваяСтрока.ПриводитьКДлине = одЗначениеЭлемента(ПравилаОбмена, одТипЧисло);
			
		ИначеЕсли ИмяУзла = "ИмяПараметраДляПередачи" Тогда
			НоваяСтрока.ИмяПараметраДляПередачи = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			
		ИначеЕсли ИмяУзла = "ПоискПоДатеНаРавенство" Тогда
			НоваяСтрока.ПоискПоДатеНаРавенство = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);
			
		ИначеЕсли (ИмяУзла = "Свойство") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		КонецЕсли;
		
	КонецЦикла;
	
	НоваяСтрока.УпрощеннаяВыгрузкаСвойства = НЕ НоваяСтрока.ПолучитьИзВходящихДанных
		И НЕ НоваяСтрока.ЕстьОбработчикПередВыгрузкой
		И НЕ НоваяСтрока.ЕстьОбработчикПриВыгрузке
		И НЕ НоваяСтрока.ЕстьОбработчикПослеВыгрузки
		И ПустаяСтрока(НоваяСтрока.ПравилоКонвертации)
		И НоваяСтрока.ТипИсточника = НоваяСтрока.ТипПриемника
		И (НоваяСтрока.ТипИсточника = "Строка" ИЛИ НоваяСтрока.ТипИсточника = "Число" ИЛИ НоваяСтрока.ТипИсточника = "Булево" ИЛИ НоваяСтрока.ТипИсточника = "Дата");
		
	НоваяСтрока.НуженУзелXMLПриВыгрузке = НоваяСтрока.ЕстьОбработчикПриВыгрузке ИЛИ НоваяСтрока.ЕстьОбработчикПослеВыгрузки;
	
КонецПроцедуры

// Осуществляет загрузку правил конвертации свойств.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//  ТаблицаСвойств - ТаблицаЗначений - таблица значений, содержащая ПКС.
//  ТаблицаПоиска  - ТаблицаЗначений - таблица значений, содержащая ПКС (синхронизирующих).
//
Процедура ЗагрузитьСвойства(ПравилаОбмена, ТаблицаСвойств, ТаблицаПоиска)

	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		Если      ИмяУзла = "Свойство" Тогда
			ЗагрузитьПКС(ПравилаОбмена, ТаблицаСвойств, ТаблицаПоиска);
		ИначеЕсли ИмяУзла = "Группа" Тогда
			ЗагрузитьПКГС(ПравилаОбмена, ТаблицаСвойств);
		ИначеЕсли (ИмяУзла = "Свойства") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		КонецЕсли;
		
	КонецЦикла;

	ТаблицаСвойств.Сортировать("Порядок");
	ТаблицаПоиска.Сортировать("Порядок");
	
КонецПроцедуры

// Осуществляет загрузку правила конвертации значений.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//  Значения       - Соответствие - соответствие значений объекта источника - строковым
//                   представлениям объекта приемника.
//  ТипИсточника   - Строка - тип объекта источника.
//
Процедура ЗагрузитьПКЗ(ПравилаОбмена, Значения, ТипИсточника)

	Источник = "";
	Приемник = "";
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		Если      ИмяУзла = "Источник" Тогда
			Источник = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
		ИначеЕсли ИмяУзла = "Приемник" Тогда
			Приемник = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
		ИначеЕсли (ИмяУзла = "Значение") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		КонецЕсли;
		
	КонецЦикла;
	
	Если РежимОбмена <> "Загрузка" Тогда
		Значения[одПолучитьЗначениеПоСтроке(Источник, ТипИсточника)] = Приемник;
	КонецЕсли;
	
КонецПроцедуры

// Осуществляет загрузку правил конвертации значений.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//  Значения       - Соответствие - соответствие значений объекта источника - строковым
//                   представлениям объекта приемника.
//  ТипИсточника   - Строка - тип объекта источника.
//
Процедура ЗагрузитьЗначения(ПравилаОбмена, Значения, ТипИсточника)

	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		Если      ИмяУзла = "Значение" Тогда
			ЗагрузитьПКЗ(ПравилаОбмена, Значения, ТипИсточника);
		ИначеЕсли (ИмяУзла = "Значения") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

// Процедура очистки ПКо у менеджеров для правил обмена.
Процедура ОчиститьПКОМенеджеров()
	
	Если Менеджеры = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Для Каждого МенеджерПравила Из Менеджеры Цикл
		МенеджерПравила.Значение.ПКО = Неопределено;
	КонецЦикла;
	
КонецПроцедуры

// Осуществляет загрузку правила конвертации объектов.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//  ЗаписьXML      - ЗаписьXML - объект типа ЗаписьXML - правила, сохраняемые в файл обмена и
//                   используемые при загрузке данных.
//
Процедура ЗагрузитьПравилоКонвертации(ПравилаОбмена, ЗаписьXML)

	ЗаписьXML.ЗаписатьНачалоЭлемента("Правило");

	НоваяСтрока = КоллекцияПравилаКонвертации().Добавить();
	
	// Значения по умолчанию
	
	НоваяСтрока.ЗапоминатьВыгруженные = Истина;
	НоваяСтрока.НеЗамещать            = Ложь;
	
	ТаблицаПоискПоТЧ = КоллекцияПоискПоТабличнымЧастям();
	НоваяСтрока.ПоискПоТабличнымЧастям = ТаблицаПоискПоТЧ;
	
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
				
		Если      ИмяУзла = "Код" Тогда
			
			Значение = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
			НоваяСтрока.Имя = Значение;
			
		ИначеЕсли ИмяУзла = "Наименование" Тогда
			
			НоваяСтрока.Наименование = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			
		ИначеЕсли ИмяУзла = "СинхронизироватьПоИдентификатору" Тогда
			
			НоваяСтрока.СинхронизироватьПоИдентификатору = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);
			одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, НоваяСтрока.СинхронизироватьПоИдентификатору);
			
		ИначеЕсли ИмяУзла = "НеСоздаватьЕслиНеНайден" Тогда
			
			НоваяСтрока.НеСоздаватьЕслиНеНайден = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);
			
		ИначеЕсли ИмяУзла = "НеВыгружатьОбъектыСвойствПоСсылкам" Тогда
			
			НоваяСтрока.НеВыгружатьОбъектыСвойствПоСсылкам = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);
						
		ИначеЕсли ИмяУзла = "ПродолжитьПоискПоПолямПоискаЕслиПоИдентификаторуНеНашли" Тогда
			
			НоваяСтрока.ПродолжитьПоискПоПолямПоискаЕслиПоИдентификаторуНеНашли = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);	
			одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, НоваяСтрока.ПродолжитьПоискПоПолямПоискаЕслиПоИдентификаторуНеНашли);
			
		ИначеЕсли ИмяУзла = "ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD" Тогда
			
			НоваяСтрока.ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);	
			одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, НоваяСтрока.ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD);
			
		ИначеЕсли ИмяУзла = "НеЗамещатьОбъектСозданныйВИнформационнойБазеПриемнике" Тогда
			// не влияет на обмен
			одЗначениеЭлемента(ПравилаОбмена, одТипБулево);	
						
		ИначеЕсли ИмяУзла = "ИспользоватьБыстрыйПоискПриЗагрузке" Тогда
			
			НоваяСтрока.ИспользоватьБыстрыйПоискПриЗагрузке = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);	
			
		ИначеЕсли ИмяУзла = "ГенерироватьНовыйНомерИлиКодЕслиНеУказан" Тогда
			
			НоваяСтрока.ГенерироватьНовыйНомерИлиКодЕслиНеУказан = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);
			одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, НоваяСтрока.ГенерироватьНовыйНомерИлиКодЕслиНеУказан);
			
		ИначеЕсли ИмяУзла = "НеЗапоминатьВыгруженные" Тогда
			
			НоваяСтрока.ЗапоминатьВыгруженные = Не одЗначениеЭлемента(ПравилаОбмена, одТипБулево);
			
		ИначеЕсли ИмяУзла = "НеЗамещать" Тогда
			
			Значение = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);
			одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
			НоваяСтрока.НеЗамещать = Значение;
			
		ИначеЕсли ИмяУзла = "ПриоритетОбъектовОбмена" Тогда
			
			// В универсальном обмене не участвует.
			одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			
		ИначеЕсли ИмяУзла = "Приемник" Тогда
			
			Значение = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
			НоваяСтрока.Приемник = Значение;
			
		ИначеЕсли ИмяУзла = "Источник" Тогда
			
			Значение = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
			
			Если РежимОбмена = "Загрузка" Тогда
				
				НоваяСтрока.Источник = Значение;
				
			Иначе
				
				Если Не ПустаяСтрока(Значение) Тогда
					          
					НоваяСтрока.ТипИсточника = Значение;
					НоваяСтрока.Источник     = Тип(Значение);
					
					Попытка
						
						Менеджеры[НоваяСтрока.Источник].ПКО = НоваяСтрока;
						
					Исключение
						
						ЗаписатьИнформациюОбОшибкеВПротокол(11, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
							Строка(НоваяСтрока.Источник));
						
					КонецПопытки; 
					
				КонецЕсли;
				
			КонецЕсли;
			
		// Свойства
		
		ИначеЕсли ИмяУзла = "Свойства" Тогда
		
			НоваяСтрока.СвойстваПоиска	= мТаблицаПравилКонвертацииСвойств.Скопировать();
			НоваяСтрока.Свойства		= мТаблицаПравилКонвертацииСвойств.Скопировать();
			
			
			Если НоваяСтрока.СинхронизироватьПоИдентификатору <> Неопределено И НоваяСтрока.СинхронизироватьПоИдентификатору Тогда
				
				СвойствоПоискаУИ = НоваяСтрока.СвойстваПоиска.Добавить();
				СвойствоПоискаУИ.Имя = "{УникальныйИдентификатор}";
				СвойствоПоискаУИ.Источник = "{УникальныйИдентификатор}";
				СвойствоПоискаУИ.Приемник = "{УникальныйИдентификатор}";
				
			КонецЕсли;
			
			ЗагрузитьСвойства(ПравилаОбмена, НоваяСтрока.Свойства, НоваяСтрока.СвойстваПоиска);

			
		// Значения
		
		ИначеЕсли ИмяУзла = "Значения" Тогда
		
			ЗагрузитьЗначения(ПравилаОбмена, НоваяСтрока.Значения, НоваяСтрока.Источник);
		
		// Обработчики событий
		
		ИначеЕсли ИмяУзла = "ПередВыгрузкой" Тогда
		
			НоваяСтрока.ПередВыгрузкой = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			НоваяСтрока.ЕстьОбработчикПередВыгрузкой = Не ПустаяСтрока(НоваяСтрока.ПередВыгрузкой);
			
		ИначеЕсли ИмяУзла = "ПриВыгрузке" Тогда
			
			НоваяСтрока.ПриВыгрузке = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			НоваяСтрока.ЕстьОбработчикПриВыгрузке    = Не ПустаяСтрока(НоваяСтрока.ПриВыгрузке);
			
		ИначеЕсли ИмяУзла = "ПослеВыгрузки" Тогда
			
			НоваяСтрока.ПослеВыгрузки = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			НоваяСтрока.ЕстьОбработчикПослеВыгрузки  = Не ПустаяСтрока(НоваяСтрока.ПослеВыгрузки);
			
		ИначеЕсли ИмяУзла = "ПослеВыгрузкиВФайл" Тогда
			
			НоваяСтрока.ПослеВыгрузкиВФайл = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			НоваяСтрока.ЕстьОбработчикПослеВыгрузкиВФайл  = Не ПустаяСтрока(НоваяСтрока.ПослеВыгрузкиВФайл);
			
		// Для загрузки
		
		ИначеЕсли ИмяУзла = "ПередЗагрузкой" Тогда
			
			Значение = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			
			
 			Если РежимОбмена = "Загрузка" Тогда
				
				НоваяСтрока.ПередЗагрузкой               = Значение;
				НоваяСтрока.ЕстьОбработчикПередЗагрузкой = Не ПустаяСтрока(Значение);
				
			Иначе
				
				одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
				
			КонецЕсли;
			
		ИначеЕсли ИмяУзла = "ПриЗагрузке" Тогда
			
			Значение = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			
			Если РежимОбмена = "Загрузка" Тогда
				
				НоваяСтрока.ПриЗагрузке               = Значение;
				НоваяСтрока.ЕстьОбработчикПриЗагрузке = Не ПустаяСтрока(Значение);
				
			Иначе
				
				одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
				
			КонецЕсли; 
			
		ИначеЕсли ИмяУзла = "ПослеЗагрузки" Тогда
			
			Значение = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			
			Если РежимОбмена = "Загрузка" Тогда
				
				НоваяСтрока.ПослеЗагрузки               = Значение;
				НоваяСтрока.ЕстьОбработчикПослеЗагрузки = Не ПустаяСтрока(Значение);
				
			Иначе
				
				одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
				
	 		КонецЕсли;
			
		ИначеЕсли ИмяУзла = "ПоследовательностьПолейПоиска" Тогда
			
			Значение = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			
			НоваяСтрока.ЕстьОбработчикПоследовательностьПолейПоиска = Не ПустаяСтрока(Значение);
			
			Если РежимОбмена = "Загрузка" Тогда
				
				НоваяСтрока.ПоследовательностьПолейПоиска = Значение;
				
			Иначе
				
				одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
				
			КонецЕсли;
			
		ИначеЕсли ИмяУзла = "ПоискПоТабличнымЧастям" Тогда
			
			Значение = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			
			Для Номер = 1 По СтрЧислоСтрок(Значение) Цикл
				
				ТекущаяСтрока = СтрПолучитьСтроку(Значение, Номер);
				
				СтрокаПоиска = ОтделитьРазделителем(ТекущаяСтрока, ":");
				
				СтрокаТаблицы = ТаблицаПоискПоТЧ.Добавить();
				СтрокаТаблицы.ИмяЭлемента = ТекущаяСтрока;
				
				СтрокаТаблицы.ПоляПоискаТЧ = РазложитьСтрокуВМассивПодстрок(СтрокаПоиска);
				
			КонецЦикла;
			
		ИначеЕсли (ИмяУзла = "Правило") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			
			Прервать;
			
		КонецЕсли;
		
	КонецЦикла;
	
	ИтоговаяСтрокаПоискаПоТЧ = "";
	
	// В приемник нужно передать информацию о полях поиска для табличных частей.
	Для Каждого СтрокаСвойств Из НоваяСтрока.Свойства Цикл
		
		Если Не СтрокаСвойств.ЭтоГруппа
			ИЛИ ПустаяСтрока(СтрокаСвойств.ВидИсточника)
			ИЛИ ПустаяСтрока(СтрокаСвойств.Приемник) Тогда
			
			Продолжить;
			
		КонецЕсли;
		
		Если ПустаяСтрока(СтрокаСвойств.СтрокаПолейПоиска) Тогда
			Продолжить;
		КонецЕсли;
		
		ИтоговаяСтрокаПоискаПоТЧ = ИтоговаяСтрокаПоискаПоТЧ + Символы.ПС + СтрокаСвойств.ВидИсточника + "." + СтрокаСвойств.Приемник + ":" + СтрокаСвойств.СтрокаПолейПоиска;
		
	КонецЦикла;
	
	ИтоговаяСтрокаПоискаПоТЧ = СокрЛП(ИтоговаяСтрокаПоискаПоТЧ);
	
	Если Не ПустаяСтрока(ИтоговаяСтрокаПоискаПоТЧ) Тогда
		
		одЗаписатьЭлемент(ЗаписьXML, "ПоискПоТабличнымЧастям", ИтоговаяСтрокаПоискаПоТЧ);	
		
	КонецЕсли;

	ЗаписьXML.ЗаписатьКонецЭлемента();

	
	// Быстрый доступ к ПКО по имени.
	
	Правила.Вставить(НоваяСтрока.Имя, НоваяСтрока);
	
КонецПроцедуры
 
// Осуществляет загрузку правил конвертации объектов.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//  ЗаписьXML      - ЗаписьXML - объект типа ЗаписьXML - правила, сохраняемые в файл обмена и
//                   используемые при загрузке данных.
//
Процедура ЗагрузитьПравилаКонвертации(ПравилаОбмена, ЗаписьXML)

	ТаблицаПравилКонвертации.Очистить();
	ОчиститьПКОМенеджеров();
	
	ЗаписьXML.ЗаписатьНачалоЭлемента("ПравилаКонвертацииОбъектов");
	
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		Если      ИмяУзла = "Правило" Тогда
			
			ЗагрузитьПравилоКонвертации(ПравилаОбмена, ЗаписьXML);
			
		ИначеЕсли (ИмяУзла = "ПравилаКонвертацииОбъектов") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			
			Прервать;
			
		КонецЕсли;
		
	КонецЦикла;

	ЗаписьXML.ЗаписатьКонецЭлемента();
	
	ТаблицаПравилКонвертации.Индексы.Добавить("Приемник");
	
КонецПроцедуры

// Осуществляет загрузку группы правил очистки данных в соответствии с форматом правил обмена.
//
// Параметры:
//  НоваяСтрока - СтрокаДереваЗначений - структура, описывающая группу правил очистки данных:
//    * Имя - Строка - идентификатор правила.
//    * Наименование - Строка - пользовательское представление правила.
// 
Процедура ЗагрузитьГруппуПОД(ПравилаОбмена, НоваяСтрока)

	НоваяСтрока.ЭтоГруппа = Истина;
	НоваяСтрока.Включить  = Число(Не одАтрибут(ПравилаОбмена, одТипБулево, "Отключить"));
	
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		ТипУзла = ПравилаОбмена.ТипУзла;
		
		Если      ИмяУзла = "Код" Тогда
			НоваяСтрока.Имя = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);

		ИначеЕсли ИмяУзла = "Наименование" Тогда
			НоваяСтрока.Наименование = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
		
		ИначеЕсли ИмяУзла = "Порядок" Тогда
			НоваяСтрока.Порядок = одЗначениеЭлемента(ПравилаОбмена, одТипЧисло);
			
		ИначеЕсли ИмяУзла = "Правило" Тогда
			СтрокаДЗ = НоваяСтрока.Строки.Добавить();
			ЗагрузитьПОД(ПравилаОбмена, СтрокаДЗ);
			
		ИначеЕсли (ИмяУзла = "Группа") И (ТипУзла = одТипУзлаXML_НачалоЭлемента) Тогда
			СтрокаДЗ = НоваяСтрока.Строки.Добавить();
			ЗагрузитьГруппуПОД(ПравилаОбмена, СтрокаДЗ);
			
		ИначеЕсли (ИмяУзла = "Группа") И (ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		КонецЕсли;
		
	КонецЦикла;
	
	Если ПустаяСтрока(НоваяСтрока.Наименование) Тогда
		НоваяСтрока.Наименование = НоваяСтрока.Имя;
	КонецЕсли; 
	
КонецПроцедуры

// Осуществляет загрузку правила очистки данных в соответствии с форматом правил обмена.
//
// Параметры:
//  НоваяСтрока - СтрокаДереваЗначений - структура, описывающая правило очистки данных:
//    * Имя - Строка - идентификатор правила.
//    * Наименование - Строка - пользовательское представление правила.
// 
Процедура ЗагрузитьПОД(ПравилаОбмена, НоваяСтрока)
	
	НоваяСтрока.Включить = Число(Не одАтрибут(ПравилаОбмена, одТипБулево, "Отключить"));
	
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		Если      ИмяУзла = "Код" Тогда
			Значение = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			НоваяСтрока.Имя = Значение;

		ИначеЕсли ИмяУзла = "Наименование" Тогда
			НоваяСтрока.Наименование = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
		
		ИначеЕсли ИмяУзла = "Порядок" Тогда
			НоваяСтрока.Порядок = одЗначениеЭлемента(ПравилаОбмена, одТипЧисло);
			
		ИначеЕсли ИмяУзла = "СпособОтбораДанных" Тогда
			НоваяСтрока.СпособОтбораДанных = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);

		ИначеЕсли ИмяУзла = "ОбъектВыборки" Тогда
			ОбъектВыборки = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			Если Не ПустаяСтрока(ОбъектВыборки) Тогда
				НоваяСтрока.ОбъектВыборки = Тип(ОбъектВыборки);
			КонецЕсли; 

		ИначеЕсли ИмяУзла = "УдалятьЗаПериод" Тогда
			НоваяСтрока.УдалятьЗаПериод = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			
		ИначеЕсли ИмяУзла = "Непосредственно" Тогда
			НоваяСтрока.Непосредственно = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);

		
		// Обработчики событий

		ИначеЕсли ИмяУзла = "ПередОбработкойПравила" Тогда
			НоваяСтрока.ПередОбработкой = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			
		ИначеЕсли ИмяУзла = "ПослеОбработкиПравила" Тогда
			НоваяСтрока.ПослеОбработки = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
		
		ИначеЕсли ИмяУзла = "ПередУдалениемОбъекта" Тогда
			НоваяСтрока.ПередУдалением = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);

		// Выход
		ИначеЕсли (ИмяУзла = "Правило") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
			
		КонецЕсли;
		
	КонецЦикла;

	
	Если ПустаяСтрока(НоваяСтрока.Наименование) Тогда
		НоваяСтрока.Наименование = НоваяСтрока.Имя;
	КонецЕсли; 
	
КонецПроцедуры

// Осуществляет загрузку правил очистки данных.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//  ЗаписьXML      - ЗаписьXML - объект типа ЗаписьXML - правила, сохраняемые в файл обмена и
//                   используемые при загрузке данных.
//
Процедура ЗагрузитьПравилаОчистки(ПравилаОбмена, ЗаписьXML)
	
 	ТаблицаПравилОчистки.Строки.Очистить();
	СтрокиДЗ = ТаблицаПравилОчистки.Строки;
	
	ЗаписьXML.ЗаписатьНачалоЭлемента("ПравилаОчисткиДанных");

	Пока ПравилаОбмена.Прочитать() Цикл
		
		ТипУзла = ПравилаОбмена.ТипУзла;
		
		Если ТипУзла = одТипУзлаXML_НачалоЭлемента Тогда
			ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
			Если РежимОбмена <> "Загрузка" Тогда
				ЗаписьXML.ЗаписатьНачалоЭлемента(ПравилаОбмена.Имя);
				Пока ПравилаОбмена.ПрочитатьАтрибут() Цикл
					ЗаписьXML.ЗаписатьАтрибут(ПравилаОбмена.Имя, ПравилаОбмена.Значение);
				КонецЦикла;
			Иначе
				Если ИмяУзла = "Правило" Тогда
					СтрокаДЗ = СтрокиДЗ.Добавить();
					ЗагрузитьПОД(ПравилаОбмена, СтрокаДЗ);
				ИначеЕсли ИмяУзла = "Группа" Тогда
					СтрокаДЗ = СтрокиДЗ.Добавить();
					ЗагрузитьГруппуПОД(ПравилаОбмена, СтрокаДЗ);
				КонецЕсли;
			КонецЕсли;
		ИначеЕсли ТипУзла = одТипУзлаXML_КонецЭлемента Тогда
			ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
			Если ИмяУзла = "ПравилаОчисткиДанных" Тогда
				Прервать;
			Иначе
				Если РежимОбмена <> "Загрузка" Тогда
					ЗаписьXML.ЗаписатьКонецЭлемента();
				КонецЕсли;
			КонецЕсли;
		ИначеЕсли ТипУзла = одТипУзлаXML_Текст Тогда
			Если РежимОбмена <> "Загрузка" Тогда
				ЗаписьXML.ЗаписатьТекст(ПравилаОбмена.Значение);
			КонецЕсли;
		КонецЕсли; 
	КонецЦикла;

	СтрокиДЗ.Сортировать("Порядок", Истина);
	
 	ЗаписьXML.ЗаписатьКонецЭлемента();
	
КонецПроцедуры

// Осуществляет загрузку алгоритма в соответствии с форматом правил обмена.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//  ЗаписьXML      - ЗаписьXML - объект типа ЗаписьXML - правила, сохраняемые в файл обмена и
//                   используемые при загрузке данных.
//
Процедура ЗагрузитьАлгоритм(ПравилаОбмена, ЗаписьXML)

	ИспользуетсяПриЗагрузке = одАтрибут(ПравилаОбмена, одТипБулево, "ИспользуетсяПриЗагрузке");
	Имя                     = одАтрибут(ПравилаОбмена, одТипСтрока, "Имя");
	
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		Если      ИмяУзла = "Текст" Тогда
			Текст = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
		ИначеЕсли (ИмяУзла = "Алгоритм") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		Иначе
			одПропустить(ПравилаОбмена);
		КонецЕсли;
		
	КонецЦикла;

	
	Если ИспользуетсяПриЗагрузке Тогда
		Если РежимОбмена = "Загрузка" Тогда
			Алгоритмы.Вставить(Имя, Текст);
		Иначе
			ЗаписьXML.ЗаписатьНачалоЭлемента("Алгоритм");
			УстановитьАтрибут(ЗаписьXML, "ИспользуетсяПриЗагрузке", Истина);
			УстановитьАтрибут(ЗаписьXML, "Имя",   Имя);
			одЗаписатьЭлемент(ЗаписьXML, "Текст", Текст);
			ЗаписьXML.ЗаписатьКонецЭлемента();
		КонецЕсли;
	Иначе
		Если РежимОбмена <> "Загрузка" Тогда
			Алгоритмы.Вставить(Имя, Текст);
		КонецЕсли;
	КонецЕсли;
	
	
КонецПроцедуры

// Осуществляет загрузку алгоритмов в соответствии с форматом правил обмена.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//  ЗаписьXML      - ЗаписьXML - объект типа ЗаписьXML - правила, сохраняемые в файл обмена и
//                   используемые при загрузке данных.
//
Процедура ЗагрузитьАлгоритмы(ПравилаОбмена, ЗаписьXML)

	Алгоритмы.Очистить();

	ЗаписьXML.ЗаписатьНачалоЭлемента("Алгоритмы");
	
	Пока ПравилаОбмена.Прочитать() Цикл
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		Если      ИмяУзла = "Алгоритм" Тогда
			ЗагрузитьАлгоритм(ПравилаОбмена, ЗаписьXML);
		ИначеЕсли (ИмяУзла = "Алгоритмы") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		КонецЕсли;
		
	КонецЦикла;

	ЗаписьXML.ЗаписатьКонецЭлемента();
	
КонецПроцедуры

// Осуществляет загрузку запроса в соответствии с форматом правил обмена.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//  ЗаписьXML      - ЗаписьXML - объект типа ЗаписьXML - правила, сохраняемые в файл обмена и
//                   используемые при загрузке данных.
//
Процедура ЗагрузитьЗапрос(ПравилаОбмена, ЗаписьXML)

	ИспользуетсяПриЗагрузке = одАтрибут(ПравилаОбмена, одТипБулево, "ИспользуетсяПриЗагрузке");
	Имя                     = одАтрибут(ПравилаОбмена, одТипСтрока, "Имя");
	
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		Если      ИмяУзла = "Текст" Тогда
			Текст = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
		ИначеЕсли (ИмяУзла = "Запрос") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		Иначе
			одПропустить(ПравилаОбмена);
		КонецЕсли;
		
	КонецЦикла;

	Если ИспользуетсяПриЗагрузке Тогда
		Если РежимОбмена = "Загрузка" Тогда
			Запрос	= Новый Запрос(Текст);
			Запросы.Вставить(Имя, Запрос);
		Иначе
			ЗаписьXML.ЗаписатьНачалоЭлемента("Запрос");
			УстановитьАтрибут(ЗаписьXML, "ИспользуетсяПриЗагрузке", Истина);
			УстановитьАтрибут(ЗаписьXML, "Имя",   Имя);
			одЗаписатьЭлемент(ЗаписьXML, "Текст", Текст);
			ЗаписьXML.ЗаписатьКонецЭлемента();
		КонецЕсли;
	Иначе
		Если РежимОбмена <> "Загрузка" Тогда
			Запрос	= Новый Запрос(Текст);
			Запросы.Вставить(Имя, Запрос);
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

// Осуществляет загрузку запросов в соответствии с форматом правил обмена.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//  ЗаписьXML      - ЗаписьXML - объект типа ЗаписьXML - правила, сохраняемые в файл обмена и
//                   используемые при загрузке данных.
//
Процедура ЗагрузитьЗапросы(ПравилаОбмена, ЗаписьXML)

	Запросы.Очистить();

	ЗаписьXML.ЗаписатьНачалоЭлемента("Запросы");
	
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		Если      ИмяУзла = "Запрос" Тогда
			ЗагрузитьЗапрос(ПравилаОбмена, ЗаписьXML);
		ИначеЕсли (ИмяУзла = "Запросы") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		КонецЕсли;
		
	КонецЦикла;

	ЗаписьXML.ЗаписатьКонецЭлемента();
	
КонецПроцедуры

// Осуществляет загрузку параметров в соответствии с форматом правил обмена.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//
Процедура ЗагрузитьПараметры(ПравилаОбмена, ЗаписьXML)

	Параметры.Очистить();
	СобытияПослеЗагрузкиПараметров.Очистить();
	ТаблицаНастройкиПараметров.Очистить();
	
	ЗаписьXML.ЗаписатьНачалоЭлемента("Параметры");
	
	Пока ПравилаОбмена.Прочитать() Цикл
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		ТипУзла = ПравилаОбмена.ТипУзла;

		Если ИмяУзла = "Параметр" И ТипУзла = одТипУзлаXML_НачалоЭлемента Тогда
			
			// Загрузка по версии правил 2.01.
			Имя                     = одАтрибут(ПравилаОбмена, одТипСтрока, "Имя");
			Наименование            = одАтрибут(ПравилаОбмена, одТипСтрока, "Наименование");
			УстанавливатьВДиалоге   = одАтрибут(ПравилаОбмена, одТипБулево, "УстанавливатьВДиалоге");
			СтрокаТипаЗначения      = одАтрибут(ПравилаОбмена, одТипСтрока, "ТипЗначения");
			ИспользуетсяПриЗагрузке = одАтрибут(ПравилаОбмена, одТипБулево, "ИспользуетсяПриЗагрузке");
			ПередаватьПараметрПриВыгрузке = одАтрибут(ПравилаОбмена, одТипБулево, "ПередаватьПараметрПриВыгрузке");
			ПравилоКонвертации = одАтрибут(ПравилаОбмена, одТипСтрока, "ПравилоКонвертации");
			АлгоритмПослеЗагрузкиПараметра = одАтрибут(ПравилаОбмена, одТипСтрока, "ПослеЗагрузкиПараметра");
			
			Если Не ПустаяСтрока(АлгоритмПослеЗагрузкиПараметра) Тогда
				
				СобытияПослеЗагрузкиПараметров.Вставить(Имя, АлгоритмПослеЗагрузкиПараметра);
				
			КонецЕсли;
			
			Если РежимОбмена = "Загрузка" И НЕ ИспользуетсяПриЗагрузке Тогда
				Продолжить;
			КонецЕсли;
			
			// Определяем типы значений и устанавливаем начальные значения.
			Если Не ПустаяСтрока(СтрокаТипаЗначения) Тогда
				
				Попытка
					ТипЗначенияДанных = Тип(СтрокаТипаЗначения);
					ТипОпределен = ИСТИНА;
				Исключение
					ТипОпределен = ЛОЖЬ;
				КонецПопытки;
				
			Иначе
				
				ТипОпределен = ЛОЖЬ;
				
			КонецЕсли;
			
			Если ТипОпределен Тогда
				ЗначениеПараметра = одПолучитьПустоеЗначение(ТипЗначенияДанных);
				Параметры.Вставить(Имя, ЗначениеПараметра);
			Иначе
				ЗначениеПараметра = "";
				Параметры.Вставить(Имя);
			КонецЕсли;
						
			Если УстанавливатьВДиалоге = ИСТИНА Тогда
				
				СтрокаТаблицы              = ТаблицаНастройкиПараметров.Добавить();
				СтрокаТаблицы.Наименование = Наименование;
				СтрокаТаблицы.Имя          = Имя;
				СтрокаТаблицы.Значение = ЗначениеПараметра;				
				СтрокаТаблицы.ПередаватьПараметрПриВыгрузке = ПередаватьПараметрПриВыгрузке;
				СтрокаТаблицы.ПравилоКонвертации = ПравилоКонвертации;
				
			КонецЕсли;
			
			Если ИспользуетсяПриЗагрузке
				И РежимОбмена = "Выгрузка" Тогда
				
				ЗаписьXML.ЗаписатьНачалоЭлемента("Параметр");
				УстановитьАтрибут(ЗаписьXML, "Имя",   Имя);
				УстановитьАтрибут(ЗаписьXML, "Наименование", Наименование);
					
				Если НЕ ПустаяСтрока(АлгоритмПослеЗагрузкиПараметра) Тогда
					УстановитьАтрибут(ЗаписьXML, "ПослеЗагрузкиПараметра", XMLСтрока(АлгоритмПослеЗагрузкиПараметра));
				КонецЕсли;
				
				ЗаписьXML.ЗаписатьКонецЭлемента();
				
			КонецЕсли;

		ИначеЕсли (ТипУзла = одТипУзлаXML_Текст) Тогда
			
			// Для совместимости с версией правил 2.0 используем загрузку из строки.
			СтрокаПараметров = ПравилаОбмена.Значение;
			Для каждого Пар Из МассивИзСтроки(СтрокаПараметров) Цикл
				Параметры.Вставить(Пар);
			КонецЦикла;
			
		ИначеЕсли (ИмяУзла = "Параметры") И (ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		КонецЕсли;
		
	КонецЦикла;

	ЗаписьXML.ЗаписатьКонецЭлемента();

КонецПроцедуры

// Осуществляет загрузку обработки в соответствии с форматом правил обмена.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//  ЗаписьXML      - ЗаписьXML - объект типа ЗаписьXML - правила, сохраняемые в файл обмена и
//                   используемые при загрузке данных.
//
Процедура ЗагрузитьОбработку(ПравилаОбмена, ЗаписьXML)

	Имя                     = одАтрибут(ПравилаОбмена, одТипСтрока, "Имя");
	Наименование            = одАтрибут(ПравилаОбмена, одТипСтрока, "Наименование");
	ЭтоОбработкаНастройки   = одАтрибут(ПравилаОбмена, одТипБулево, "ЭтоОбработкаНастройки");
	
	ИспользуетсяПриВыгрузке = одАтрибут(ПравилаОбмена, одТипБулево, "ИспользуетсяПриВыгрузке");
	ИспользуетсяПриЗагрузке = одАтрибут(ПравилаОбмена, одТипБулево, "ИспользуетсяПриЗагрузке");

	СтрокаПараметров        = одАтрибут(ПравилаОбмена, одТипСтрока, "Параметры");
	
	ХранилищеОбработки      = одЗначениеЭлемента(ПравилаОбмена, одТипХранилищеЗначения);

	ПараметрыДопОбработок.Вставить(Имя, МассивИзСтроки(СтрокаПараметров));
	
	
	Если ИспользуетсяПриЗагрузке Тогда
		Если РежимОбмена = "Загрузка" Тогда
			
		Иначе
			ЗаписьXML.ЗаписатьНачалоЭлемента("Обработка");
			УстановитьАтрибут(ЗаписьXML, "ИспользуетсяПриЗагрузке", Истина);
			УстановитьАтрибут(ЗаписьXML, "Имя",                     Имя);
			УстановитьАтрибут(ЗаписьXML, "Наименование",            Наименование);
			УстановитьАтрибут(ЗаписьXML, "ЭтоОбработкаНастройки",   ЭтоОбработкаНастройки);
			ЗаписьXML.ЗаписатьТекст(XMLСтрока(ХранилищеОбработки));
			ЗаписьXML.ЗаписатьКонецЭлемента();
		КонецЕсли;
	КонецЕсли;
	
	Если ЭтоОбработкаНастройки Тогда
		Если (РежимОбмена = "Загрузка") И ИспользуетсяПриЗагрузке Тогда
			ОбработкиНастройкиЗагрузки.Добавить(Имя, Наименование, , );
			
		ИначеЕсли (РежимОбмена = "Выгрузка") И ИспользуетсяПриВыгрузке Тогда
			ОбработкиНастройкиВыгрузки.Добавить(Имя, Наименование, , );
			
		КонецЕсли; 
	КонецЕсли; 
	
КонецПроцедуры

// Осуществляет загрузку внешних обработок в соответствии с форматом правил обмена.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//  ЗаписьXML      - ЗаписьXML - объект типа ЗаписьXML - правила, сохраняемые в файл обмена и
//                   используемые при загрузке данных.
//
Процедура ЗагрузитьОбработки(ПравилаОбмена, ЗаписьXML)

	ДопОбработки.Очистить();
	ПараметрыДопОбработок.Очистить();
	
	ОбработкиНастройкиВыгрузки.Очистить();
	ОбработкиНастройкиЗагрузки.Очистить();

	ЗаписьXML.ЗаписатьНачалоЭлемента("Обработки");
	
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		Если      ИмяУзла = "Обработка" Тогда
			ЗагрузитьОбработку(ПравилаОбмена, ЗаписьXML);
		ИначеЕсли (ИмяУзла = "Обработки") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		КонецЕсли;
		
	КонецЦикла;

	ЗаписьXML.ЗаписатьКонецЭлемента();
	
КонецПроцедуры

// Осуществляет загрузку группы правил выгрузки данных в соответствии с форматом правил обмена.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//  НоваяСтрока    - СтрокаДереваЗначений - структура, описывающая группу правил выгрузки данных:
//    * Имя - Строка - идентификатор правила.
//    * Наименование - Строка - пользовательское представление правила.
//
Процедура ЗагрузитьГруппуПВД(ПравилаОбмена, НоваяСтрока)

	НоваяСтрока.ЭтоГруппа = Истина;
	НоваяСтрока.Включить  = Число(Не одАтрибут(ПравилаОбмена, одТипБулево, "Отключить"));
	
	Пока ПравилаОбмена.Прочитать() Цикл
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		ТипУзла = ПравилаОбмена.ТипУзла;
		Если      ИмяУзла = "Код" Тогда
			НоваяСтрока.Имя = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);

		ИначеЕсли ИмяУзла = "Наименование" Тогда
			НоваяСтрока.Наименование = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
		
		ИначеЕсли ИмяУзла = "Порядок" Тогда
			НоваяСтрока.Порядок = одЗначениеЭлемента(ПравилаОбмена, одТипЧисло);
			
		ИначеЕсли ИмяУзла = "Правило" Тогда
			СтрокаДЗ = НоваяСтрока.Строки.Добавить();
			ЗагрузитьПВД(ПравилаОбмена, СтрокаДЗ);
			
		ИначеЕсли (ИмяУзла = "Группа") И (ТипУзла = одТипУзлаXML_НачалоЭлемента) Тогда
			СтрокаДЗ = НоваяСтрока.Строки.Добавить();
			ЗагрузитьГруппуПВД(ПравилаОбмена, СтрокаДЗ);
					
		ИначеЕсли (ИмяУзла = "Группа") И (ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		КонецЕсли;
		
	КонецЦикла;
	
	Если ПустаяСтрока(НоваяСтрока.Наименование) Тогда
		НоваяСтрока.Наименование = НоваяСтрока.Имя;
	КонецЕсли; 
	
КонецПроцедуры

// Осуществляет загрузку правила выгрузки данных в соответствии с форматом правил обмена.
//
// Параметры:
//  ПравилаОбмена  - ЧтениеXML - объект типа ЧтениеXML.
//  НоваяСтрока    - СтрокаДереваЗначений - структура, описывающая правило выгрузки данных:
//    * Имя - Строка - идентификатор правила.
//    * Наименование - Строка - пользовательское представление правила.
//
Процедура ЗагрузитьПВД(ПравилаОбмена, НоваяСтрока)

	НоваяСтрока.Включить = Число(Не одАтрибут(ПравилаОбмена, одТипБулево, "Отключить"));
	
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		Если      ИмяУзла = "Код" Тогда
			НоваяСтрока.Имя = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);

		ИначеЕсли ИмяУзла = "Наименование" Тогда
			НоваяСтрока.Наименование = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
		
		ИначеЕсли ИмяУзла = "Порядок" Тогда
			НоваяСтрока.Порядок = одЗначениеЭлемента(ПравилаОбмена, одТипЧисло);
			
		ИначеЕсли ИмяУзла = "СпособОтбораДанных" Тогда
			НоваяСтрока.СпособОтбораДанных = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			
		ИначеЕсли ИмяУзла = "ВыбиратьДанныеДляВыгрузкиОднимЗапросом" Тогда
			НоваяСтрока.ВыбиратьДанныеДляВыгрузкиОднимЗапросом = одЗначениеЭлемента(ПравилаОбмена, одТипБулево);
			
		ИначеЕсли ИмяУзла = "НеВыгружатьОбъектыСозданныеВБазеПриемнике" Тогда
			// Параметр игнорируется при обмене данными.
			одЗначениеЭлемента(ПравилаОбмена, одТипБулево);

		ИначеЕсли ИмяУзла = "ОбъектВыборки" Тогда
			ОбъектВыборки = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			Если Не ПустаяСтрока(ОбъектВыборки) Тогда
				НоваяСтрока.ОбъектВыборки = Тип(ОбъектВыборки);
			КонецЕсли;
			// Для поддержки отбора с помощью построителя.
			Если СтрНайти(ОбъектВыборки, "Ссылка.") Тогда
				НоваяСтрока.ИмяОбъектаДляЗапроса = СтрЗаменить(ОбъектВыборки, "Ссылка.", ".");
			Иначе
				НоваяСтрока.ИмяОбъектаДляЗапросаРегистра = СтрЗаменить(ОбъектВыборки, "Запись.", ".");
			КонецЕсли;

		ИначеЕсли ИмяУзла = "КодПравилаКонвертации" Тогда
			НоваяСтрока.ПравилоКонвертации = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);

		// Обработчики событий

		ИначеЕсли ИмяУзла = "ПередОбработкойПравила" Тогда
			НоваяСтрока.ПередОбработкой = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			
		ИначеЕсли ИмяУзла = "ПослеОбработкиПравила" Тогда
			НоваяСтрока.ПослеОбработки = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
		
		ИначеЕсли ИмяУзла = "ПередВыгрузкойОбъекта" Тогда
			НоваяСтрока.ПередВыгрузкой = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);

		ИначеЕсли ИмяУзла = "ПослеВыгрузкиОбъекта" Тогда
			НоваяСтрока.ПослеВыгрузки = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
        		
		ИначеЕсли (ИмяУзла = "Правило") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		КонецЕсли;
		
	КонецЦикла;

	Если ПустаяСтрока(НоваяСтрока.Наименование) Тогда
		НоваяСтрока.Наименование = НоваяСтрока.Имя;
	КонецЕсли; 
	
КонецПроцедуры

// Осуществляет загрузку правил выгрузки данных в соответствии с форматом правил обмена.
//
// Параметры:
//  ПравилаОбмена - ЧтениеXML - объект типа ЧтениеXML.
//
Процедура ЗагрузитьПравилаВыгрузки(ПравилаОбмена)

	ТаблицаПравилВыгрузки.Строки.Очистить();

	СтрокиДЗ = ТаблицаПравилВыгрузки.Строки;
	
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		Если ИмяУзла = "Правило" Тогда
			
			СтрокаДЗ = СтрокиДЗ.Добавить();
			ЗагрузитьПВД(ПравилаОбмена, СтрокаДЗ);
			
		ИначеЕсли ИмяУзла = "Группа" Тогда
			
			СтрокаДЗ = СтрокиДЗ.Добавить();
			ЗагрузитьГруппуПВД(ПравилаОбмена, СтрокаДЗ);
			
		ИначеЕсли (ИмяУзла = "ПравилаВыгрузкиДанных") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			
			Прервать;
			
		КонецЕсли;
		
	КонецЦикла;

	СтрокиДЗ.Сортировать("Порядок", Истина);

КонецПроцедуры

#КонецОбласти

#Область ПроцедурыЭкспортаОбработчиковИАлгоритмовВTXTФайлИзПравилОбмена

// Выгружает обработчики событий и алгоритмы во временный текстовый файл 
// (во временный каталог пользователя).
// Формирует модуль отладки с обработчиками и алгоритмами и со всеми 
// необходимыми глобальными переменными, обертками общих функций и комментариями.
//
// Параметры:
//  Отказ - Булево - флаг отказа от создания модуля отладки. Возникает если не
//          удалось прочесть правила обмена.
//
Процедура ВыгрузитьОбработчикиСобытий(Отказ) Экспорт
	
	ИнициализироватьВедениеПротоколаОбменаДляЭкспортаОбработчиков();
	
	РежимОбработкиДанных = мРежимыОбработкиДанных.ЭкспортОбработчиковСобытий;
	
	ФлагОшибки = Ложь;
	
	ЗагрузитьПравилаОбменаДляЭкспортаОбработчиков();
	
	Если ФлагОшибки Тогда
		Отказ = Истина;
		Возврат;
	КонецЕсли; 
	
	ДополнитьПравилаИнтерфейсамиОбработчиков(Конвертация, ТаблицаПравилКонвертации, ТаблицаПравилВыгрузки, ТаблицаПравилОчистки);
	
	Если РежимОтладкиАлгоритмов = мРежимыОтладкиАлгоритмов.ИнтеграцияКода Тогда
		
		ПолучитьПолныйКодАлгоритмовСУчетомВложенности();
		
	КонецЕсли;
	
	ИмяВременногоФайлаОбработчиковСобытий = ПолучитьНовоеУникальноеИмяВременногоФайла(ИмяВременногоФайлаОбработчиковСобытий);
	
	Результат = Новый ЗаписьТекста(ИмяВременногоФайлаОбработчиковСобытий, КодировкаТекста.ANSI);
	
	мМакетОбщиеПроцедурыФункции = ПолучитьМакет("ОбщиеПроцедурыФункции");
	
	// Выводим комментарии.
	ДобавитьВПотокКомментарий(Результат, "Шапка");
	ДобавитьВПотокКомментарий(Результат, "ПеременныеОбработки");
	
	// Выводим служебный код.
	ДобавитьВПотокСлужебныйКод(Результат, "ПеременныеОбработки");
	
	// Выгружаем глобальные обработчики.
	ВыгрузитьОбработчикиКонвертации(Результат);
	
	// Выгружаем ПВД.
	ДобавитьВПотокКомментарий(Результат, "ПВД", ТаблицаПравилВыгрузки.Строки.Количество() <> 0);
	ВыгрузитьОбработчикиПравилВыгрузкиДанных(Результат, ТаблицаПравилВыгрузки.Строки);
	
	// Выгружаем ПОД.
	ДобавитьВПотокКомментарий(Результат, "ПОД", ТаблицаПравилОчистки.Строки.Количество() <> 0);
	ВыгрузитьОбработчикиПравилОчисткиДанных(Результат, ТаблицаПравилОчистки.Строки);
	
	// Выгружаем ПКО, ПКС, ПКГС.
	ВыгрузитьОбработчикиПравилКонвертации(Результат);
	
	Если РежимОтладкиАлгоритмов = мРежимыОтладкиАлгоритмов.ПроцедурныйВызов Тогда
		
		// Выгружаем Алгоритмы со стандартными параметрами (параметрами по умолчанию).
		ВыгрузитьАлгоритмы(Результат);
		
	КонецЕсли; 
	
	// Выводим комментарии
	ДобавитьВПотокКомментарий(Результат, "Предупреждение");
	ДобавитьВПотокКомментарий(Результат, "ОбщиеПроцедурыФункции");
		
	// Выводим общие процедуры и функции в поток.
	ДобавитьВПотокСлужебныйКод(Результат, "ОбщиеПроцедурыФункции");

	// Выводим конструктор внешней обработки.
	ВыгрузитьКонструкторВнешнейОбработки(Результат);
	
	// Выводим деструктор
	ДобавитьВПотокСлужебныйКод(Результат, "Деструктор");
	
	Результат.Закрыть();
	
	ЗавершитьВедениеПротоколаОбмена();
	
	Если ЭтоИнтерактивныйРежим Тогда
		
		Если ФлагОшибки Тогда
			
			СообщитьПользователю(НСтр("ru = 'При выгрузке обработчиков были обнаружены ошибки.'"));
			
		Иначе
			
			СообщитьПользователю(НСтр("ru = 'Обработчики успешно выгружены.'"));
			
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

// Очищает переменные со структурой правил обмена.
//
// Параметры:
//  Нет.
//  
Процедура ОчиститьПравилаОбмена()
	
	ТаблицаПравилВыгрузки.Строки.Очистить();
	ТаблицаПравилОчистки.Строки.Очистить();
	ТаблицаПравилКонвертации.Очистить();
	Алгоритмы.Очистить();
	Запросы.Очистить();

	// Обработки
	ДопОбработки.Очистить();
	ПараметрыДопОбработок.Очистить();
	ОбработкиНастройкиВыгрузки.Очистить();
	ОбработкиНастройкиЗагрузки.Очистить();

КонецПроцедуры  

// Производит загрузку правил обмена из файла-правил или файла-данных.
//
// Параметры:
//  Нет.
//  
Процедура ЗагрузитьПравилаОбменаДляЭкспортаОбработчиков()
	
	ОчиститьПравилаОбмена();
	
	Если ОбработчикиСобытийЧитаемИзФайлаПравилОбмена Тогда
		
		РежимОбмена = ""; // Выгрузка

		ЗагрузитьПравилаОбмена();
		
		мБылиПрочитаныПравилаОбменаПриЗагрузке = Ложь;
		
		ИнициализироватьПервоначальныеЗначенияПараметров();
		
	Иначе // файл данных
		
		РежимОбмена = "Загрузка"; 
		
		Если ПустаяСтрока(ИмяФайлаОбмена) Тогда
			ЗаписатьВПротоколВыполнения(15);
			Возврат;
		КонецЕсли;
		
		ОткрытьФайлЗагрузки(Истина);
		
		// При наличии флага обработка потребует перечитать
		// правила при попытке выгрузки данных.
		мБылиПрочитаныПравилаОбменаПриЗагрузке = Истина;

	КонецЕсли;
	
КонецПроцедуры

// Выгружает глобальные обработчики конвертации в текстовый файл.
// При выгрузке обработчиков из файла с данными содержимое обработчика "Конвертация_ПослеЗагрузкиПараметров"
// не выгружается, т.к. код обработчика находится не в узле правил обмена, а в отдельном узле.
// При выгрузке обработчиков из файла правил этот алгоритм выгружается как и другие.
//
// Параметры:
//  Результат - ЗаписьТекста - объект типа ЗаписьТекста - для вывода обработчиков в текстовый файл.
//
Процедура ВыгрузитьОбработчикиКонвертации(Результат)
	
	ДобавитьВПотокКомментарий(Результат, "Конвертация");
	
	Для Каждого Элемент Из ИменаОбработчиков.Конвертация Цикл
		
		ДобавитьВПотокОбработчикКонвертации(Результат, Элемент.Ключ);
		
	КонецЦикла; 
	
КонецПроцедуры 

// Выгружает обработчики правил выгрузки данных в текстовый файл.
//
// Параметры:
//  Результат    - ЗаписьТекста - объект типа ЗаписьТекста - для вывода обработчиков в текстовый файл.
//  СтрокиДерева - КоллекцияСтрокДереваЗначений - объект типа КоллекцияСтрокДереваЗначений - содержит ПВД данного уровня
//                                                дерева значений.
//
Процедура ВыгрузитьОбработчикиПравилВыгрузкиДанных(Результат, СтрокиДерева)
	
	Для Каждого Правило Из СтрокиДерева Цикл
		
		Если Правило.ЭтоГруппа Тогда
			
			ВыгрузитьОбработчикиПравилВыгрузкиДанных(Результат, Правило.Строки); 
			
		Иначе
			
			Для Каждого Элемент Из ИменаОбработчиков.ПВД Цикл
				
				ДобавитьВПотокОбработчик(Результат, Правило, "ПВД", Элемент.Ключ);
				
			КонецЦикла; 
			
		КонецЕсли; 
		
	КонецЦикла; 
	
КонецПроцедуры  

// Выгружает обработчики правил очистки данных в текстовый файл.
//
// Параметры:
//  Результат    - ЗаписьТекста - объект типа ЗаписьТекста - для вывода обработчиков в текстовый файл.
//  СтрокиДерева - КоллекцияСтрокДереваЗначений - объект типа КоллекцияСтрокДереваЗначений - содержит ПОД данного уровня
//                                                дерева значений.
//
Процедура ВыгрузитьОбработчикиПравилОчисткиДанных(Результат, СтрокиДерева)
	
	Для Каждого Правило Из СтрокиДерева Цикл
		
		Если Правило.ЭтоГруппа Тогда
			
			ВыгрузитьОбработчикиПравилОчисткиДанных(Результат, Правило.Строки); 
			
		Иначе
			
			Для Каждого Элемент Из ИменаОбработчиков.ПОД Цикл
				
				ДобавитьВПотокОбработчик(Результат, Правило, "ПОД", Элемент.Ключ);
				
			КонецЦикла; 
			
		КонецЕсли; 
		
	КонецЦикла; 
	
КонецПроцедуры  

// Выгружает обработчики правил конвертации: ПКО, ПКС, ПКГС в текстовый файл.
//
// Параметры:
//  Результат    - ЗаписьТекста - объект типа ЗаписьТекста - для вывода обработчиков в текстовый файл.
//
Процедура ВыгрузитьОбработчикиПравилКонвертации(Результат)
	
	ВывестиКомментарий = ТаблицаПравилКонвертации.Количество() <> 0;
	
	// Выгружаем ПКО.
	ДобавитьВПотокКомментарий(Результат, "ПКО", ВывестиКомментарий);
	
	Для Каждого ПКО Из ТаблицаПравилКонвертации Цикл
		
		Для Каждого Элемент Из ИменаОбработчиков.ПКО Цикл
			
			ДобавитьВПотокОбработчикПКО(Результат, ПКО, Элемент.Ключ);
			
		КонецЦикла; 
		
	КонецЦикла; 
	
	// Выгружаем ПКС и ПКГС.
	ДобавитьВПотокКомментарий(Результат, "ПКС", ВывестиКомментарий);
	
	Для Каждого ПКО Из ТаблицаПравилКонвертации Цикл
		
		ВыгрузитьОбработчикиПравилКонвертацииСвойств(Результат, ПКО.СвойстваПоиска);
		ВыгрузитьОбработчикиПравилКонвертацииСвойств(Результат, ПКО.Свойства);
		
	КонецЦикла; 
	
КонецПроцедуры 

// Выгружает обработчики правил конвертации свойств в текстовый файл.
//
// Параметры:
//  Результат - ЗаписьТекста - объект типа ЗаписьТекста - для вывода обработчиков в текстовый файл.
//  ПКС       - ТаблицаЗначений - содержит правила конвертации свойств или групп свойств объекта.
//
Процедура ВыгрузитьОбработчикиПравилКонвертацииСвойств(Результат, ПКС)
	
	Для Каждого Правило Из ПКС Цикл
		
		Если Правило.ЭтоГруппа Тогда // ПКГС
			
			Для Каждого Элемент Из ИменаОбработчиков.ПКГС Цикл
				
				ДобавитьВПотокОбработчикПКО(Результат, Правило, Элемент.Ключ);
				
			КонецЦикла; 

			ВыгрузитьОбработчикиПравилКонвертацииСвойств(Результат, Правило.ПравилаГруппы);
			
		Иначе
			
			Для Каждого Элемент Из ИменаОбработчиков.ПКС Цикл
				
				ДобавитьВПотокОбработчикПКО(Результат, Правило, Элемент.Ключ);
				
			КонецЦикла;
			
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

// Выгружает алгоритмы в текстовый файл.
//
// Параметры:
//  Результат - ЗаписьТекста - объект типа ЗаписьТекста - для вывода алгоритмов в текстовый файл.
//
Процедура ВыгрузитьАлгоритмы(Результат)
	
	// Комментарий к блоку "Алгоритмы".
	ДобавитьВПотокКомментарий(Результат, "Алгоритмы", Алгоритмы.Количество() <> 0);
	
	Для Каждого Алгоритм Из Алгоритмы Цикл
		
		ДобавитьВПотокАлгоритм(Результат, Алгоритм);
		
	КонецЦикла; 
	
КонецПроцедуры  

// Выгружает конструктор внешней обработки в текстовый файл.
//  Если режим отладки алгоритмов - "алгоритмы отлаживать как процедуры", то в конструктор добавляется структура
//  "Алгоритмы".
//  Ключ элемента структуры - имя алгоритма, значение - интерфейс вызова процедуры, содержащей код алгоритма.
//
// Параметры:
//  Результат    - ЗаписьТекста - объект типа ЗаписьТекста - для вывода обработчиков в текстовый файл.
//
Процедура ВыгрузитьКонструкторВнешнейОбработки(Результат)
	
	// Выводим комментарий
	ДобавитьВПотокКомментарий(Результат, "Конструктор");
	
	ТелоПроцедуры = ПолучитьСлужебныйКод("Конструктор_ТелоПроцедуры");

	Если РежимОтладкиАлгоритмов = мРежимыОтладкиАлгоритмов.ПроцедурныйВызов Тогда
		
		ТелоПроцедуры = ТелоПроцедуры + ПолучитьСлужебныйКод("Конструктор_ТелоПроцедуры_ПроцедурныйВызовАлгоритмов");
		
		// Добавляем в тело конструктора вызовы Алгоритмов.
		Для Каждого Алгоритм Из Алгоритмы Цикл
			
			КлючАлгоритма = СокрЛП(Алгоритм.Ключ);
			
			ИнтерфейсАлгоритма = ПолучитьИнтерфейсАлгоритма(КлючАлгоритма) + ";";
			
			ИнтерфейсАлгоритма = СтрЗаменить(СтрЗаменить(ИнтерфейсАлгоритма, Символы.ПС, " ")," ","");
			
			ТелоПроцедуры = ТелоПроцедуры + Символы.ПС 
			   + "Алгоритмы.Вставить(""" + КлючАлгоритма + """, """ + ИнтерфейсАлгоритма + """);";

			
		КонецЦикла; 
		
	ИначеЕсли РежимОтладкиАлгоритмов = мРежимыОтладкиАлгоритмов.ИнтеграцияКода Тогда
		
		ТелоПроцедуры = ТелоПроцедуры + ПолучитьСлужебныйКод("Конструктор_ТелоПроцедуры_ИнтеграцияКодаАлгоритмов");
		
	ИначеЕсли РежимОтладкиАлгоритмов = мРежимыОтладкиАлгоритмов.НеИспользовать Тогда
		
		ТелоПроцедуры = ТелоПроцедуры + ПолучитьСлужебныйКод("Конструктор_ТелоПроцедуры_НеИспользоватьОтладкуАлгоритмов");
		
	КонецЕсли; 
	
	ИнтерфейсПроцедурыВнешнейОбработки = "Процедура " + ПолучитьИнтерфейсПроцедурыВнешнейОбработки("Конструктор") + " Экспорт";
	
	ДобавитьВПотокПолныйОбработчик(Результат, ИнтерфейсПроцедурыВнешнейОбработки, ТелоПроцедуры);
	
КонецПроцедуры  

// Добавляет в объект "Результат" обработчик ПКО, ПКС или ПКГС.
//
// Параметры:
//  Результат      - ЗаписьТекста - объект типа ЗаписьТекста - для вывода обработчика в текстовый файл.
//  Правило        - СтрокаТаблицыЗначений - с правилами конвертации объекта.
//  ИмяОбработчика - Строка - имя обработчика.
//
Процедура ДобавитьВПотокОбработчикПКО(Результат, Правило, ИмяОбработчика)
	
	Если Не Правило["ЕстьОбработчик" + ИмяОбработчика] Тогда
		Возврат;
	КонецЕсли; 
	
	ИнтерфейсОбработчика = "Процедура " + Правило["ИнтерфейсОбработчика" + ИмяОбработчика] + " Экспорт";
	
	ДобавитьВПотокПолныйОбработчик(Результат, ИнтерфейсОбработчика, Правило[ИмяОбработчика]);
	
КонецПроцедуры  

// Добавляет в объект "Результат" код алгоритма.
//
// Параметры:
//  Результат - ЗаписьТекста - объект типа ЗаписьТекста - для вывода обработчика в текстовый файл.
//  Алгоритм  - КлючИЗначение - элемент структуры, алгоритм для выгрузки.
//
Процедура ДобавитьВПотокАлгоритм(Результат, Алгоритм)
	
	ИнтерфейсАлгоритма = "Процедура " + ПолучитьИнтерфейсАлгоритма(Алгоритм.Ключ);

	ДобавитьВПотокПолныйОбработчик(Результат, ИнтерфейсАлгоритма, Алгоритм.Значение);
	
КонецПроцедуры  

// Добавляет в объект "Результат" обработчик ПВД или ПОД.
//
// Параметры:
//  Результат      - ЗаписьТекста - объект типа ЗаписьТекста - для вывода обработчика в текстовый файл.
//  Правило        - строка дерева значений с правилами.
//  ПрефиксОбработчика - Строка - префикс обработчика: "ПВД" или "ПОД".
//  ИмяОбработчика - Строка - имя обработчика.
//
Процедура ДобавитьВПотокОбработчик(Результат, Правило, ПрефиксОбработчика, ИмяОбработчика)
	
	Если ПустаяСтрока(Правило[ИмяОбработчика]) Тогда
		Возврат;
	КонецЕсли;
	
	ИнтерфейсОбработчика = "Процедура " + Правило["ИнтерфейсОбработчика" + ИмяОбработчика] + " Экспорт";
	
	ДобавитьВПотокПолныйОбработчик(Результат, ИнтерфейсОбработчика, Правило[ИмяОбработчика]);
	
КонецПроцедуры  

// Добавляет в объект "Результат" глобальный обработчик конвертации.
//
// Параметры:
//  Результат      - ЗаписьТекста - объект типа ЗаписьТекста - для вывода обработчика в текстовый файл.
//  ИмяОбработчика - Строка - имя обработчика.
//
Процедура ДобавитьВПотокОбработчикКонвертации(Результат, ИмяОбработчика)
	
	АлгоритмОбработчика = "";
	
	Если Конвертация.Свойство(ИмяОбработчика, АлгоритмОбработчика) И Не ПустаяСтрока(АлгоритмОбработчика) Тогда
		
		ИнтерфейсОбработчика = "Процедура " + Конвертация["ИнтерфейсОбработчика" + ИмяОбработчика] + " Экспорт";
		
		ДобавитьВПотокПолныйОбработчик(Результат, ИнтерфейсОбработчика, АлгоритмОбработчика);
		
	КонецЕсли;
	
КонецПроцедуры  

// Добавляет в объект "Результат" процедуру с кодом обработчика или кодом алгоритма.
//
// Параметры:
//  Результат            - ЗаписьТекста - объект типа ЗаписьТекста - для вывода процедуры в текстовый файл.
//  ИнтерфейсОбработчика - Строка - полное описание интерфейса обработчика:
//                         имя процедуры, параметры процедуры, ключевое слово "Экспорт".
//  Обработчик           - Строка - тело обработчика или алгоритма.
//
Процедура ДобавитьВПотокПолныйОбработчик(Результат, ИнтерфейсОбработчика, Обработчик)
	
	СтрокаПрефикса = Символы.Таб;
	
	Результат.ЗаписатьСтроку("");
	
	Результат.ЗаписатьСтроку(ИнтерфейсОбработчика);
	
	Результат.ЗаписатьСтроку("");
	
	Для Индекс = 1 По СтрЧислоСтрок(Обработчик) Цикл
		
		СтрокаОбработчика = СтрПолучитьСтроку(Обработчик, Индекс);
		
		// В режиме отладки алгоритмов "Интеграция кода" вставляем код алгоритмов 
		// непосредственно в код обработчика. Код алгоритма вставляем взамен его вызова.
		// В коде алгоритмов уже учтена вложенность алгоритмов друг в друга.
		Если РежимОтладкиАлгоритмов = мРежимыОтладкиАлгоритмов.ИнтеграцияКода Тогда
			
			АлгоритмыОбработчика = ПолучитьАлгоритмыОбработчика(СтрокаОбработчика);
			
			Если АлгоритмыОбработчика.Количество() <> 0 Тогда // В этой строке есть вызовы алгоритмов.
				
				// Получаем начальное смещение кода алгоритма относительно текущего кода обработчика.
				СтрокаПрефиксаДляВложенногоКода = ПолучитьПрефиксДляВложенногоАлгоритма(СтрокаОбработчика, СтрокаПрефикса);
				
				Для Каждого Алгоритм Из АлгоритмыОбработчика Цикл
					
					ОбработчикАлгоритма = АлгоритмыИнтегрированные[Алгоритм];
					
					Для ИндексСтрокиАлгоритма = 1 По СтрЧислоСтрок(ОбработчикАлгоритма) Цикл
						
						Результат.ЗаписатьСтроку(СтрокаПрефиксаДляВложенногоКода + СтрПолучитьСтроку(ОбработчикАлгоритма, ИндексСтрокиАлгоритма));
						
					КонецЦикла;	
					
				КонецЦикла;
				
			КонецЕсли;
		КонецЕсли;

		Результат.ЗаписатьСтроку(СтрокаПрефикса + СтрокаОбработчика);
		
	КонецЦикла;
	
	Результат.ЗаписатьСтроку("");
	Результат.ЗаписатьСтроку("КонецПроцедуры");
	
КонецПроцедуры

// Добавляет в объект "Результат" комментарий.
//
// Параметры:
//  Результат          - ЗаписьТекста - объект типа ЗаписьТекста - для вывода комментария в текстовый файл.
//  ИмяОбласти         - Строка - имя области текстового макета "мМакетОбщиеПроцедурыФункции"
//                       в которой содержится требуемый комментарий.
//  ВывестиКомментарий - Булево - признак необходимости вывода комментария.
//
Процедура ДобавитьВПотокКомментарий(Результат, ИмяОбласти, ВывестиКомментарий = Истина)
	
	Если Не ВывестиКомментарий Тогда
		Возврат;
	КонецЕсли; 
	
	// Получаем комментарии обработчиков по названию области.
	ТекущаяОбласть = мМакетОбщиеПроцедурыФункции.ПолучитьОбласть(ИмяОбласти+"_Комментарий");
	
	КомментарийИзМакета = СокрЛП(ПолучитьТекстПоОбластиБезНазванияОбласти(ТекущаяОбласть));
	
	// Исключаем последний перевод строки.
	КомментарийИзМакета = Сред(КомментарийИзМакета, 1, СтрДлина(КомментарийИзМакета));
	
	Результат.ЗаписатьСтроку(Символы.ПС + Символы.ПС + КомментарийИзМакета);
	
КонецПроцедуры  

// Добавляет в объект "Результат" служебный код: параметры, общие процедуры и функции, деструктор внешней обработки.
//
// Параметры:
//  Результат          - ЗаписьТекста - объект типа ЗаписьТекста - для вывода служебного кода в текстовый файл.
//  ИмяОбласти         - Строка - имя области текстового макета "мМакетОбщиеПроцедурыФункции"
//                       в которой содержится требуемый служебный код.
//
Процедура ДобавитьВПотокСлужебныйКод(Результат, ИмяОбласти)
	
	// Получаем текст области
	ТекущаяОбласть = мМакетОбщиеПроцедурыФункции.ПолучитьОбласть(ИмяОбласти);
	
	Текст = СокрЛП(ПолучитьТекстПоОбластиБезНазванияОбласти(ТекущаяОбласть));
	
	Текст = Сред(Текст, 1, СтрДлина(Текст)); // Исключаем последний перевод строки.
	
	Результат.ЗаписатьСтроку(Символы.ПС + Символы.ПС + Текст);
	
КонецПроцедуры  

// Получает служебный код из указанной области макета "мМакетОбщиеПроцедурыФункции".
//
// Параметры:
//  ИмяОбласти - Строка - имя области текстового макета "мМакетОбщиеПроцедурыФункции".
//  
// Возвращаемое значение:
//  Строка - текст из макета
//
Функция ПолучитьСлужебныйКод(ИмяОбласти)
	
	// Получаем текст области
	ТекущаяОбласть = мМакетОбщиеПроцедурыФункции.ПолучитьОбласть(ИмяОбласти);
	
	Возврат ПолучитьТекстПоОбластиБезНазванияОбласти(ТекущаяОбласть);
КонецФункции

#КонецОбласти

#Область ПроцедурыИФункцииПолученияПолногоКодаАлгоритмовСУчетомИхВложенности

// Формирует полный код алгоритмов с учетом их вложенности друг в друга.
//
// Параметры:
//  Нет.
//  
Процедура ПолучитьПолныйКодАлгоритмовСУчетомВложенности()
	
	// Заполняем структуру интегрированных алгоритмов.
	АлгоритмыИнтегрированные = Новый Структура;
	
	Для Каждого Алгоритм Из Алгоритмы Цикл
		
		АлгоритмыИнтегрированные.Вставить(Алгоритм.Ключ, ЗаменитьВызовыАлгоритмовКодомЭтихАлгоритмовВОбработчике(Алгоритм.Значение, Алгоритм.Ключ, Новый Массив));
		
	КонецЦикла; 
	
КонецПроцедуры 

// Добавляет строку "ОбработчикНовый" комментарием к вставке кода очередного алгоритма.
//
// Параметры:
//  ОбработчикНовый - Строка - итоговая строка содержащая полный код алгоритма с учетом вложенности алгоритмов.
//  ИмяАлгоритма    - Строка - имя алгоритма.
//  СтрокаПрефикса  - Строка - задает начальное смещение выводимого комментария.
//  Заголовок       - Строка - наименование комментария: "{НАЧАЛО АЛГОРИТМА}", "{КОНЕЦ АЛГОРИТМА}"...
//
Процедура ЗаписатьЗаголовокБлокаАлгоритма(ОбработчикНовый, ИмяАлгоритма, СтрокаПрефикса, Заголовок) 
	
	ЗаголовокАлгоритма = "//============================ " + Заголовок + " """ + ИмяАлгоритма + """ ============================";
	
	ОбработчикНовый = ОбработчикНовый + Символы.ПС;
	ОбработчикНовый = ОбработчикНовый + Символы.ПС + СтрокаПрефикса + ЗаголовокАлгоритма;
	ОбработчикНовый = ОбработчикНовый + Символы.ПС;
	
КонецПроцедуры  

// Дополняет массив "АлгоритмыОбработчика" именами алгоритмов, которые вызываются 
// из переданной процедуре строки обработчика "СтрокаОбработчика".
//
// Параметры:
//  СтрокаОбработчика - Строка - строка обработчика или алгоритма в которой выполняется поиск вызовов алгоритмов.
//  АлгоритмыОбработчика - Массив- содержит имена алгоритмов, которые вызывается из заданного обработчика.
//  
Процедура ПолучитьАлгоритмыСтрокиОбработчика(СтрокаОбработчика, АлгоритмыОбработчика)
	
	СтрокаОбработчика = ВРег(СтрокаОбработчика);
	
	ШаблонПоиска = "АЛГОРИТМЫ.";
	
	ДлинаСтрокиШаблона = СтрДлина(ШаблонПоиска);
	
	СимволНачальный = СтрНайти(СтрокаОбработчика, ШаблонПоиска);
	
	Если СимволНачальный = 0 Тогда
		// В данной строке нет алгоритмов или все алгоритмы из этой строки уже учтены.
		Возврат; 
	КонецЕсли;
	
	// Проверка на наличие признака того, что этот оператор закомментирован.
	СтрокаОбработчикаДоВызоваАлгоритма = Лев(СтрокаОбработчика, СимволНачальный);
	
	Если СтрНайти(СтрокаОбработчикаДоВызоваАлгоритма, "//") <> 0  Тогда 
		// Этот оператор и все последующие закомментированы.
		// Выходим из цикла.
		Возврат;
	КонецЕсли; 
	
	СтрокаОбработчика = Сред(СтрокаОбработчика, СимволНачальный + ДлинаСтрокиШаблона);
	
	СимволКонечный = СтрНайти(СтрокаОбработчика, ")") - 1;
	
	ИмяАлгоритма = Сред(СтрокаОбработчика, 1, СимволКонечный); 
	
	АлгоритмыОбработчика.Добавить(СокрЛП(ИмяАлгоритма));
	
	// Пробегаем строку обработчика до конца, 
	// пока все вызовы алгоритмов из этой строки не будут учтены.
	ПолучитьАлгоритмыСтрокиОбработчика(СтрокаОбработчика, АлгоритмыОбработчика);
	
КонецПроцедуры 

// Функция возвращает измененный код алгоритма с учетом вложенных алгоритмов. Вместо оператора вызова
// алгоритма "Выполнить(Алгоритмы.Алгоритм_1);" вставляется полный код вызываемого алгоритма 
// со сдвигом на величину "СтрокаПрефикса".
// Функция рекурсивно вызывает саму себя до тех по, пока все вложенные алгоритмы не будут учтены.
//
// Параметры:
//  Обработчик                 - Строка - исходный код алгоритма.
//  СтрокаПрефикса             - Строка - значение смещения вставляемого кода алгоритма.
//  АлгоритмВладелец           - Строка - имя алгоритма, являющегося родительским по отношению 
//                                        к алгоритму, код которого обрабатывается этой функцией.
//  МассивЗапрошенныхЭлементов - Массив - содержит имена алгоритмов которые уже были обработаны в данной ветке рекурсии.
//                                        Необходим для предотвращения бесконечной рекурсии функции
//                                        и вывода предупреждения об ошибке.
//  
// Возвращаемое значение:
//  Строка - измененный код алгоритма с учетом вложенных алгоритмов.
// 
Функция ЗаменитьВызовыАлгоритмовКодомЭтихАлгоритмовВОбработчике(Обработчик, АлгоритмВладелец, МассивЗапрошенныхЭлементов, Знач СтрокаПрефикса = "")
	
	МассивЗапрошенныхЭлементов.Добавить(ВРег(АлгоритмВладелец));
	
	// Инициализируем возвращаемое значение.
	ОбработчикНовый = "";
	
	ЗаписатьЗаголовокБлокаАлгоритма(ОбработчикНовый, АлгоритмВладелец, СтрокаПрефикса, НСтр("ru = '{НАЧАЛО АЛГОРИТМА}'"));
	
	Для Индекс = 1 По СтрЧислоСтрок(Обработчик) Цикл
		
		СтрокаОбработчика = СтрПолучитьСтроку(Обработчик, Индекс);
		
		АлгоритмыОбработчика = ПолучитьАлгоритмыОбработчика(СтрокаОбработчика);
		
		Если АлгоритмыОбработчика.Количество() <> 0 Тогда // В этой строке есть вызовы алгоритмов.
			
			// Получаем начальное смещение кода алгоритма относительно текущего кода.
			СтрокаПрефиксаДляВложенногоКода = ПолучитьПрефиксДляВложенногоАлгоритма(СтрокаОбработчика, СтрокаПрефикса);
				
			// Разворачиваем полный код каждого алгоритма, 
			// который был вызван из строки "СтрокаОбработчика".
			Для Каждого Алгоритм Из АлгоритмыОбработчика Цикл
				
				Если МассивЗапрошенныхЭлементов.Найти(ВРег(Алгоритм)) <> Неопределено Тогда // Рекурсивный вызов алгоритма.
					
					ЗаписатьЗаголовокБлокаАлгоритма(ОбработчикНовый, Алгоритм, СтрокаПрефиксаДляВложенногоКода, НСтр("ru = '{РЕКУРСИВНЫЙ ВЫЗОВ АЛГОРИТМА}'"));
					
					СтрокаОператора = НСтр("ru = '%1 ""РЕКУРСИВНЫЙ ВЫЗОВ АЛГОРИТМА: %2"";'");
					СтрокаОператора = ПодставитьПараметрыВСтроку(СтрокаОператора, "ВызватьИсключение", Алгоритм);
					
					ОбработчикНовый = ОбработчикНовый + Символы.ПС + СтрокаПрефиксаДляВложенногоКода + СтрокаОператора;
					
					ЗаписатьЗаголовокБлокаАлгоритма(ОбработчикНовый, Алгоритм, СтрокаПрефиксаДляВложенногоКода, НСтр("ru = '{РЕКУРСИВНЫЙ ВЫЗОВ АЛГОРИТМА}'"));
					
					СтруктураЗаписи = Новый Структура;
					СтруктураЗаписи.Вставить("Алгоритм_1", АлгоритмВладелец);
					СтруктураЗаписи.Вставить("Алгоритм_2", Алгоритм);
					
					ЗаписатьВПротоколВыполнения(79, СтруктураЗаписи);
					
				Иначе
					
					ОбработчикНовый = ОбработчикНовый + ЗаменитьВызовыАлгоритмовКодомЭтихАлгоритмовВОбработчике(Алгоритмы[Алгоритм], Алгоритм, СкопироватьМассив(МассивЗапрошенныхЭлементов), СтрокаПрефиксаДляВложенногоКода);
					
				КонецЕсли; 
				
			КонецЦикла;
			
		КонецЕсли; 
		
		ОбработчикНовый = ОбработчикНовый + Символы.ПС + СтрокаПрефикса + СтрокаОбработчика; 
		
	КонецЦикла;
	
	ЗаписатьЗаголовокБлокаАлгоритма(ОбработчикНовый, АлгоритмВладелец, СтрокаПрефикса, НСтр("ru = '{КОНЕЦ АЛГОРИТМА}'"));
	
	Возврат ОбработчикНовый;
	
КонецФункции

// Копирует переданный массив и возвращает новый массив.
//
// Параметры:
//  МассивИсточник - Массив - источник для получения нового массива копированием.
//  
// Возвращаемое значение:
//  Массив - массив, полученный копированием из переданного массива.
// 
Функция СкопироватьМассив(МассивИсточник)
	
	НовыйМассив = Новый Массив;
	
	Для Каждого ЭлементМассива Из МассивИсточник Цикл
		
		НовыйМассив.Добавить(ЭлементМассива);
		
	КонецЦикла; 
	
	Возврат НовыйМассив;
КонецФункции 

// Возвращает массив с именами алгоритмов, которые были обнаружены в теле переданного обработчика.
//
// Параметры:
//  Обработчик - Строка - тело обработчика.
//  
// Возвращаемое значение:
//  Массив - массив с именами алгоритмов, которые присутствуют в переданном обработчике.
//
Функция ПолучитьАлгоритмыОбработчика(Обработчик)
	
	// Инициализируем возвращаемое значение.
	АлгоритмыОбработчика = Новый Массив;
	
	Для Индекс = 1 По СтрЧислоСтрок(Обработчик) Цикл
		
		СтрокаОбработчика = СокрЛ(СтрПолучитьСтроку(Обработчик, Индекс));
		
		Если СтрНачинаетсяС(СтрокаОбработчика, "//") Тогда //Строка закомментирована, ее пропускаем.
			Продолжить;
		КонецЕсли;
		
		ПолучитьАлгоритмыСтрокиОбработчика(СтрокаОбработчика, АлгоритмыОбработчика);
		
	КонецЦикла;
	
	Возврат АлгоритмыОбработчика;
КонецФункции 

// Получает строку префикса для вывода кода вложенного алгоритма.
//
// Параметры:
//  СтрокаОбработчика - Строка - строка из которой извлекается значение смещения вызова
//                      (смещение при котором производится вызов алгоритма).
//  СтрокаПрефикса    - Строка - начальное смещение.
// Возвращаемое значение:
//  Строка - итоговое смещение кода алгоритма.
// 
Функция ПолучитьПрефиксДляВложенногоАлгоритма(СтрокаОбработчика, СтрокаПрефикса)
	
	СтрокаОбработчика = ВРег(СтрокаОбработчика);
	
	НомерПозицииШаблонаВыполнить = СтрНайти(СтрокаОбработчика, "ВЫПОЛНИТЬ");
	
	СтрокаПрефиксаДляВложенногоКода = СтрокаПрефикса + Лев(СтрокаОбработчика, НомерПозицииШаблонаВыполнить - 1) + Символы.Таб;
	
	// Если в строке обработчика был вызов алгоритма (алгоритмов), то строку полностью удаляем из кода.
	СтрокаОбработчика = "";
	
	Возврат СтрокаПрефиксаДляВложенногоКода;
КонецФункции 

#КонецОбласти

#Область ФункцииФормированияУникальногоИмениОбработчиковСобытий

// Формирует интерфейс обработчика ПКС, ПКГС (уникальное имя процедуры с параметрами соответствующего обработчика).
//
// Параметры:
//  ПКО            - СтрокаТаблицыЗначений - содержит правило конвертации объекта.
//  ПКГС           - СтрокаТаблицыЗначений - содержит правило конвертации группы свойств.
//  Правило        - СтрокаТаблицыЗначений - содержит правило конвертации свойств объекта.
//  ИмяОбработчика - Строка - имя обработчика события.
//
// Возвращаемое значение:
//  Строка - интерфейс обработчика.
//
Функция ПолучитьИнтерфейсОбработчикаПКС(ПКО, ПКГС, Правило, ИмяОбработчика)
	
	ПрефиксИмени = ?(Правило.ЭтоГруппа, "ПКГС", "ПКС");
	ИмяОбласти   = ПрефиксИмени + "_" + ИмяОбработчика;
	
	ИмяВладельца = "_" + СокрЛП(ПКО.Имя);
	
	ИмяРодителя  = "";
	
	Если ПКГС <> Неопределено Тогда
		
		Если Не ПустаяСтрока(ПКГС.ВидПриемника) Тогда 
			
			ИмяРодителя = "_" + СокрЛП(ПКГС.Приемник);	
			
		КонецЕсли; 
		
	КонецЕсли; 
	
	ИмяПриемника = "_" + СокрЛП(Правило.Приемник);
	ВидПриемника = "_" + СокрЛП(Правило.ВидПриемника);
	
	КодСвойства = СокрЛП(Правило.Имя);
	
	ПолноеИмяОбработчика = ИмяОбласти + ИмяВладельца + ИмяРодителя + ИмяПриемника + ВидПриемника + КодСвойства;
	
	Возврат ПолноеИмяОбработчика + "(" + ПолучитьПараметрыОбработчика(ИмяОбласти) + ")";
КонецФункции 

// Формирует интерфейс обработчика ПКО, ПВД, ПОД (уникальное имя процедуры с параметрами соответствующего обработчика).
//
// Параметры:
//  Правило            - СтрокаТаблицыЗначений - ПКО, ПВД, ПОД:
//    * Имя - Строка - имя правила.
//  ПрефиксОбработчика - Строка - принимает значения: "ПКО", "ПВД", "ПОД".
//  ИмяОбработчика     - Строка - имя обработчика события для данного правила.
//
// Возвращаемое значение:
//  Строка - интерфейс обработчика.
// 
Функция ПолучитьИнтерфейсОбработчика(Правило, ПрефиксОбработчика, ИмяОбработчика)
	
	ИмяОбласти = ПрефиксОбработчика + "_" + ИмяОбработчика;
	
	ИмяПравила = "_" + СокрЛП(Правило.Имя);
	
	ПолноеИмяОбработчика = ИмяОбласти + ИмяПравила;
	
	Возврат ПолноеИмяОбработчика + "(" + ПолучитьПараметрыОбработчика(ИмяОбласти) + ")";
КонецФункции 

// Формирует интерфейс глобального обработчика конвертации (уникальное имя процедуры с параметрами соответствующего
// обработчика).
//
// Параметры:
//  ИмяОбработчика - Строка - имя обработчика события конвертации.
//
// Возвращаемое значение:
//  Строка - интерфейс обработчика.
// 
Функция ПолучитьИнтерфейсОбработчикаКонвертация(ИмяОбработчика)
	
	ИмяОбласти = "Конвертация_" + ИмяОбработчика;
	
	ПолноеИмяОбработчика = ИмяОбласти;
	
	Возврат ПолноеИмяОбработчика + "(" + ПолучитьПараметрыОбработчика(ИмяОбласти) + ")";
КонецФункции 

// Формирует интерфейс процедуры (конструктора или деструктора) для внешней обработки.
//
// Параметры:
//  ИмяПроцедуры - Строка - имя процедуры.
//
// Возвращаемое значение:
//  Строка - интерфейс процедуры.
// 
Функция ПолучитьИнтерфейсПроцедурыВнешнейОбработки(ИмяПроцедуры)
	
	ИмяОбласти = "Обработка_" + ИмяПроцедуры;
	
	ПолноеИмяОбработчика = ИмяПроцедуры;
	
	Возврат ПолноеИмяОбработчика + "(" + ПолучитьПараметрыОбработчика(ИмяОбласти) + ")";
КонецФункции 

// Формирует интерфейс алгоритма для внешней обработки.
// Для всех алгоритмов получаем одинаковый набор параметров по умолчанию.
//
// Параметры:
//  ИмяАлгоритма - Строка - имя алгоритма.
//
// Возвращаемое значение:
//  Строка - интерфейс алгоритма.
// 
Функция ПолучитьИнтерфейсАлгоритма(ИмяАлгоритма)
	
	ПолноеИмяОбработчика = "Алгоритм_" + ИмяАлгоритма;
	
	ИмяОбласти = "Алгоритм_ПоУмолчанию";
	
	Возврат ПолноеИмяОбработчика + "(" + ПолучитьПараметрыОбработчика(ИмяОбласти) + ")";
КонецФункции 

Функция ПолучитьСтрокуВызоваОбработчика(Правило, ИмяОбработчика)
	
	Возврат "ВнешняяОбработкаОбработчиковСобытий." + Правило["ИнтерфейсОбработчика" + ИмяОбработчика] + ";";
	
КонецФункции 

Функция ПолучитьТекстПоОбластиБезНазванияОбласти(Область)
	
	ТекстОбласти = Область.ПолучитьТекст();
	
	Если СтрНайти(ТекстОбласти, "#Область") > 0 Тогда
	
		ПервыйПереводСтроки = СтрНайти(ТекстОбласти, Символы.ПС);
		
		ТекстОбласти = Сред(ТекстОбласти, ПервыйПереводСтроки + 1);
		
	КонецЕсли;
	
	Возврат ТекстОбласти;
	
КонецФункции

Функция ПолучитьПараметрыОбработчика(ИмяОбласти)
	
	СтрокаПеревода = Символы.ПС + "                                           ";
	
	ПараметрыОбработчика = "";
	
	ИтогоСтрока = "";
	
	Область = мМакетПараметровОбработчиков.ПолучитьОбласть(ИмяОбласти);
	
	ОбластьПараметров = Область.Области[ИмяОбласти];
	
	Для НомерСтроки = ОбластьПараметров.Верх По ОбластьПараметров.Низ Цикл
		
		ТекущаяОбласть = Область.ПолучитьОбласть(НомерСтроки, 2, НомерСтроки, 2);
		
		Параметр = СокрЛП(ТекущаяОбласть.ТекущаяОбласть.Текст);
		
		Если Не ПустаяСтрока(Параметр) Тогда
			
			ПараметрыОбработчика = ПараметрыОбработчика + Параметр + ", ";
			
			ИтогоСтрока = ИтогоСтрока + Параметр;
			
		КонецЕсли; 
		
		Если СтрДлина(ИтогоСтрока) > 50 Тогда
			
			ИтогоСтрока = "";
			
			ПараметрыОбработчика = ПараметрыОбработчика + СтрокаПеревода;
			
		КонецЕсли; 
		
	КонецЦикла;
	
	ПараметрыОбработчика = СокрЛП(ПараметрыОбработчика);
	
	// Убираем последний знак "," и возвращаем строку.
	
	Возврат Сред(ПараметрыОбработчика, 1, СтрДлина(ПараметрыОбработчика) - 1); 
КонецФункции 

#КонецОбласти

#Область ПроцедурыСозданияИнтерфейсаВызоваОбработчиковВПравилахОбмена

// Дополняет коллекцию значений правил очистки данных интерфейсами обработчиков.
//
// Параметры:
//  ТаблицаПОД   - ДеревоЗначений - содержит правила очистки данных.
//  СтрокиДерева - КоллекцияСтрокДереваЗначений - объект типа КоллекцияСтрокДереваЗначений - содержит ПОД данного уровня
//                                                дерева значений.
//
Процедура ДополнитьИнтерфейсамиОбработчиковПравилаОчисткиДанных(ТаблицаПОД, СтрокиДерева)
	
	Для Каждого Правило Из СтрокиДерева Цикл
		
		Если Правило.ЭтоГруппа Тогда
			
			ДополнитьИнтерфейсамиОбработчиковПравилаОчисткиДанных(ТаблицаПОД, Правило.Строки); 
			
		Иначе
			
			Для Каждого Элемент Из ИменаОбработчиков.ПОД Цикл
				
				ДобавитьИнтерфейсОбработчика(ТаблицаПОД, Правило, "ПОД", Элемент.Ключ);
				
			КонецЦикла; 
			
		КонецЕсли; 
		
	КонецЦикла; 
	
КонецПроцедуры  

// Дополняет коллекцию значений правил выгрузки данных интерфейсами обработчиков.
//
// Параметры:
//  ТаблицаПВД   - ДеревоЗначений - содержит правила выгрузки данных.
//  СтрокиДерева - КоллекцияСтрокДереваЗначений - объект типа КоллекцияСтрокДереваЗначений - содержит ПВД данного уровня
//                                                дерева значений.
//
Процедура ДополнитьИнтерфейсамиОбработчиковПравилаВыгрузкиДанных(ТаблицаПВД, СтрокиДерева) 
	
	Для Каждого Правило Из СтрокиДерева Цикл
		
		Если Правило.ЭтоГруппа Тогда
			
			ДополнитьИнтерфейсамиОбработчиковПравилаВыгрузкиДанных(ТаблицаПВД, Правило.Строки); 
			
		Иначе
			
			Для Каждого Элемент Из ИменаОбработчиков.ПВД Цикл
				
				ДобавитьИнтерфейсОбработчика(ТаблицаПВД, Правило, "ПВД", Элемент.Ключ);
				
			КонецЦикла; 
			
		КонецЕсли; 
		
	КонецЦикла; 
	
КонецПроцедуры  

// Дополняет структуру конвертации интерфейсами обработчиков.
//
// Параметры:
//  СтруктураКонвертация - Структура - содержит правила конвертации и глобальные обработчики.
//  
Процедура ДополнитьИнтерфейсамиОбработчиковПравилаКонвертации(СтруктураКонвертация) 
	
	Для Каждого Элемент Из ИменаОбработчиков.Конвертация Цикл
		
		ДобавитьИнтерфейсОбработчикаКонвертации(СтруктураКонвертация, Элемент.Ключ);
		
	КонецЦикла; 
	
КонецПроцедуры  

// Дополняет коллекцию значений правил конвертации объектов интерфейсами обработчиков.
//
// Параметры:
//  ТаблицаПКО - см. КоллекцияПравилаКонвертации
//  
Процедура ДополнитьИнтерфейсамиОбработчиковПравилаКонвертацииОбъектов(ТаблицаПКО)
	
	Для Каждого ПКО Из ТаблицаПКО Цикл
		
		Для Каждого Элемент Из ИменаОбработчиков.ПКО Цикл
			
			ДобавитьИнтерфейсОбработчикаПКО(ТаблицаПКО, ПКО, Элемент.Ключ);
			
		КонецЦикла; 
		
		// Добавляем интерфейсы для ПКС.
		ДополнитьИнтерфейсамиОбработчиковПКС(ПКО, ПКО.СвойстваПоиска);
		ДополнитьИнтерфейсамиОбработчиковПКС(ПКО, ПКО.Свойства);
		
	КонецЦикла; 
	
КонецПроцедуры

// Дополняет коллекцию значений правил конвертации свойств объектов интерфейсами обработчиков.
//
// Параметры:
//  ПКО - СтрокаТаблицыЗначений    - содержит правило конвертации объекта.
//  ПравилаКонвертацииСвойствОбъекта - ТаблицаЗначений - содержит правила конвертации свойств или группы свойств
//                                                       объекта из правила ПКО.
//  ПКГС - СтрокаТаблицыЗначений   - содержит правило конвертации группы свойств.
//
Процедура ДополнитьИнтерфейсамиОбработчиковПКС(ПКО, ПравилаКонвертацииСвойствОбъекта, ПКГС = Неопределено)
	
	Для Каждого ПКС Из ПравилаКонвертацииСвойствОбъекта Цикл
		
		Если ПКС.ЭтоГруппа Тогда // ПКГС
			
			Для Каждого Элемент Из ИменаОбработчиков.ПКГС Цикл
				
				ДобавитьИнтерфейсОбработчикаПКС(ПравилаКонвертацииСвойствОбъекта, ПКО, ПКГС, ПКС, Элемент.Ключ);
				
			КонецЦикла; 

			ДополнитьИнтерфейсамиОбработчиковПКС(ПКО, ПКС.ПравилаГруппы, ПКС);
			
		Иначе
			
			Для Каждого Элемент Из ИменаОбработчиков.ПКС Цикл
				
				ДобавитьИнтерфейсОбработчикаПКС(ПравилаКонвертацииСвойствОбъекта, ПКО, ПКГС, ПКС, Элемент.Ключ);
				
			КонецЦикла; 
			
		КонецЕсли; 
		
	КонецЦикла; 
	
КонецПроцедуры  

Процедура ДобавитьИнтерфейсОбработчика(Таблица, Правило, ПрефиксОбработчика, ИмяОбработчика) 
	
	Если ПустаяСтрока(Правило[ИмяОбработчика]) Тогда
		Возврат;
	КонецЕсли;
	
	ИмяПоля = "ИнтерфейсОбработчика" + ИмяОбработчика;
	
	ДобавитьНедостающиеКолонки(Таблица.Колонки, ИмяПоля);
		
	Правило[ИмяПоля] = ПолучитьИнтерфейсОбработчика(Правило, ПрефиксОбработчика, ИмяОбработчика);
	
КонецПроцедуры 

Процедура ДобавитьИнтерфейсОбработчикаПКО(Таблица, Правило, ИмяОбработчика) 
	
	Если Не Правило["ЕстьОбработчик" + ИмяОбработчика] Тогда
		Возврат;
	КонецЕсли; 
	
	ИмяПоля = "ИнтерфейсОбработчика" + ИмяОбработчика;
	
	ДобавитьНедостающиеКолонки(Таблица.Колонки, ИмяПоля);
	
	Правило[ИмяПоля] = ПолучитьИнтерфейсОбработчика(Правило, "ПКО", ИмяОбработчика);
  
КонецПроцедуры 

Процедура ДобавитьИнтерфейсОбработчикаПКС(Таблица, ПКО, ПКГС, ПКС, ИмяОбработчика) 
	
	Если Не ПКС["ЕстьОбработчик" + ИмяОбработчика] Тогда
		Возврат;
	КонецЕсли; 
	
	ИмяПоля = "ИнтерфейсОбработчика" + ИмяОбработчика;
	
	ДобавитьНедостающиеКолонки(Таблица.Колонки, ИмяПоля);
	
	ПКС[ИмяПоля] = ПолучитьИнтерфейсОбработчикаПКС(ПКО, ПКГС, ПКС, ИмяОбработчика);
	
КонецПроцедуры  

Процедура ДобавитьИнтерфейсОбработчикаКонвертации(СтруктураКонвертация, ИмяОбработчика)
	
	АлгоритмОбработчика = "";
	
	Если СтруктураКонвертация.Свойство(ИмяОбработчика, АлгоритмОбработчика) И Не ПустаяСтрока(АлгоритмОбработчика) Тогда
		
		ИмяПоля = "ИнтерфейсОбработчика" + ИмяОбработчика;
		
		СтруктураКонвертация.Вставить(ИмяПоля);
		
		СтруктураКонвертация[ИмяПоля] = ПолучитьИнтерфейсОбработчикаКонвертация(ИмяОбработчика); 
		
	КонецЕсли;
	
КонецПроцедуры  

#КонецОбласти

#Область ПроцедурыРаботыСПравиламиОбмена

Функция ОпределитьПоВерсииПлатформыПриемникаПлатформу(ВерсияПлатформы)
	
	Если СтрНайти(ВерсияПлатформы, "8.") > 0 Тогда
		
		Возврат "V8";
		
	Иначе
		
		Возврат "V7";
		
	КонецЕсли;	
	
КонецФункции

// Восстанавливает правила из внутреннего формата.
//
// Параметры:
// 
Процедура ВосстановитьПравилаИзВнутреннегоФормата() Экспорт

	Если СохраненныеНастройки = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	СтруктураПравил = СохраненныеНастройки.Получить(); // см. ОписаниеСтруктурыПравил

	ТаблицаПравилВыгрузки      = СтруктураПравил.ТаблицаПравилВыгрузки;
	ТаблицаПравилКонвертации   = СтруктураПравил.ТаблицаПравилКонвертации;
	Алгоритмы                  = СтруктураПравил.Алгоритмы;
	ЗапросыДляВосстановления   = СтруктураПравил.Запросы;
	Конвертация                = СтруктураПравил.Конвертация;
	мXMLПравила                = СтруктураПравил.мXMLПравила;
	ТаблицаНастройкиПараметров = СтруктураПравил.ТаблицаНастройкиПараметров;
	Параметры                  = СтруктураПравил.Параметры;
	
	ДополнитьСлужебныеТаблицыКолонками();
	
	СтруктураПравил.Свойство("ВерсияПлатформыПриемника", ВерсияПлатформыПриемника);
	
	ПлатформаПриемника = ОпределитьПоВерсииПлатформыПриемникаПлатформу(ВерсияПлатформыПриемника);
		
	ЕстьГлобальныйОбработчикПередВыгрузкойОбъекта    = Не ПустаяСтрока(Конвертация.ПередВыгрузкойОбъекта);
	ЕстьГлобальныйОбработчикПослеВыгрузкиОбъекта     = Не ПустаяСтрока(Конвертация.ПослеВыгрузкиОбъекта);
	ЕстьГлобальныйОбработчикПередЗагрузкойОбъекта    = Не ПустаяСтрока(Конвертация.ПередЗагрузкойОбъекта);
	ЕстьГлобальныйОбработчикПослеЗагрузкиОбъекта     = Не ПустаяСтрока(Конвертация.ПослеЗагрузкиОбъекта);
	ЕстьГлобальныйОбработчикПередКонвертациейОбъекта = Не ПустаяСтрока(Конвертация.ПередКонвертациейОбъекта);

	// Восстанавливаем запросы
	Запросы.Очистить();
	Для Каждого ЭлементСтруктуры Из ЗапросыДляВосстановления Цикл
		Запрос = Новый Запрос(ЭлементСтруктуры.Значение);
		Запросы.Вставить(ЭлементСтруктуры.Ключ, Запрос);
	КонецЦикла;

	ИнициализироватьМенеджерыИСообщения();
	
	Правила.Очистить();
	ОчиститьПКОМенеджеров();
	
	Если РежимОбмена = "Выгрузка" Тогда
	
		Для Каждого СтрокаТаблицы Из КоллекцияПравилаКонвертации() Цикл
			Правила.Вставить(СтрокаТаблицы.Имя, СтрокаТаблицы);
			
			Источник = СтрокаТаблицы.Источник;

			Если Источник <> Неопределено Тогда
				
				Попытка
					Если ТипЗнч(Источник) = одТипСтрока Тогда
						Менеджеры[Тип(Источник)].ПКО = СтрокаТаблицы;
					Иначе
						Менеджеры[Источник].ПКО = СтрокаТаблицы;
					КонецЕсли;
				Исключение
					ЗаписатьИнформациюОбОшибкеВПротокол(11, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), Строка(Источник));
				КонецПопытки;
				
			КонецЕсли;

		КонецЦикла;
	
	КонецЕсли;	
	
КонецПроцедуры

// Выполняет инициализацию параметров значениями по умолчанию, из правил обмена.
//
// Параметры:
//  Нет.
// 
Процедура ИнициализироватьПервоначальныеЗначенияПараметров() Экспорт
	
	Для Каждого ТекПараметр Из Параметры Цикл
		
		УстановитьЗначениеПараметраВТаблице(ТекПараметр.Ключ, ТекПараметр.Значение);
		
	КонецЦикла;
	
КонецПроцедуры

#КонецОбласти

#Область ОбработкаПравилОчистки

Процедура ВыполнитьУдалениеОбъекта(Объект, Свойства, УдалитьНепосредственно)
	
	ИмяТипа = Свойства.ИмяТипа;
	
	Если ИмяТипа = "РегистрСведений" Тогда
		
		Объект.Удалить();
		
	Иначе
		
		Если (ИмяТипа = "Справочник"
			Или ИмяТипа = "ПланВидовХарактеристик"
			Или ИмяТипа = "ПланСчетов"
			Или ИмяТипа = "ПланВидовРасчета")
			И Объект.Предопределенный Тогда
			
			Возврат;
			
		КонецЕсли;
		
		Если УдалитьНепосредственно Тогда
			
			Объект.Удалить();
			
		Иначе
			
			УстановитьПометкуУдаленияУОбъекта(Объект, Истина, Свойства.ИмяТипа);
			
		КонецЕсли;
			
	КонецЕсли;	
	
КонецПроцедуры

// Очищает данные по указанному правилу.
//
// Параметры:
//   Правило - СтрокаТаблицыЗначений - ссылка на правило очистки данных:
//     * Имя - Строка - имя правила.
// 
Процедура ОчиститьДанныеПоПравилу(Правило)
	
	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	// Обработчик ПередОбработкой

	Отказ			= Ложь;
	ВыборкаДанных	= Неопределено;

	ИсходящиеДанные	= Неопределено;


	// Обработчик ПередОбработкойПравилаОчистки
	Если Не ПустаяСтрока(Правило.ПередОбработкой) Тогда
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(Правило, "ПередОбработкой"));
				
			Иначе
				
				Выполнить(Правило.ПередОбработкой);
				
			КонецЕсли;
			
		Исключение
			
			ЗаписатьИнформациюОбОшибкеОбработчикаОчисткиДанных(27, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				Правило.Имя, "", "ПередОбработкойПравилаОчистки");
			
		КонецПопытки;
		
		Если Отказ Тогда
		
			Возврат;
			
		КонецЕсли;
		
	КонецЕсли;
	
	// Стандартная выборка
	
	Свойства = Менеджеры[Правило.ОбъектВыборки];
	
	Если Правило.СпособОтбораДанных = "СтандартнаяВыборка" Тогда
		
		ИмяТипа = Свойства.ИмяТипа;
		
		Если ИмяТипа = "РегистрБухгалтерии" 
			ИЛИ ИмяТипа = "Константы" Тогда
			
			Возврат;
			
		КонецЕсли;
		
		НужныВсеПоля  = Не ПустаяСтрока(Правило.ПередУдалением);
		
		Выборка = ПолучитьВыборкуДляВыгрузкиОчисткиДанных(Свойства, ИмяТипа, Истина, Правило.Непосредственно, НужныВсеПоля);
		
		Пока Выборка.Следующий() Цикл
			
			Если ИмяТипа =  "РегистрСведений" Тогда
				
				МенеджерЗаписи = Свойства.Менеджер.СоздатьМенеджерЗаписи(); 
				ЗаполнитьЗначенияСвойств(МенеджерЗаписи, Выборка);
									
				УдалениеОбъектаВыборки(МенеджерЗаписи, Правило, Свойства, ИсходящиеДанные);
					
			Иначе
					
				УдалениеОбъектаВыборки(Выборка.Ссылка.ПолучитьОбъект(), Правило, Свойства, ИсходящиеДанные);
					
			КонецЕсли;
				
		КонецЦикла;
		
	ИначеЕсли Правило.СпособОтбораДанных = "ПроизвольныйАлгоритм" Тогда
		
		Если ВыборкаДанных <> Неопределено Тогда
			
			Выборка = ПолучитьВыборкуДляВыгрузкиПоПроизвольномуАлгоритму(ВыборкаДанных);
			
			Если Выборка <> Неопределено Тогда
				
				Пока Выборка.Следующий() Цикл
										
					Если ИмяТипа =  "РегистрСведений" Тогда
				
						МенеджерЗаписи = Свойства.Менеджер.СоздатьМенеджерЗаписи(); 
						ЗаполнитьЗначенияСвойств(МенеджерЗаписи, Выборка);
											
						УдалениеОбъектаВыборки(МенеджерЗаписи, Правило, Свойства, ИсходящиеДанные);				
											
					Иначе
							
						УдалениеОбъектаВыборки(Выборка.Ссылка.ПолучитьОбъект(), Правило, Свойства, ИсходящиеДанные);
							
					КонецЕсли;					
					
				КонецЦикла;	
				
			Иначе
				
				Для каждого Объект Из ВыборкаДанных Цикл
					
					УдалениеОбъектаВыборки(Объект.ПолучитьОбъект(), Правило, Свойства, ИсходящиеДанные);
					
				КонецЦикла;
				
			КонецЕсли;
			
		КонецЕсли; 
			
	КонецЕсли; 

	
	// Обработчик ПослеОбработкиПравилаОчистки

	Если Не ПустаяСтрока(Правило.ПослеОбработки) Тогда
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(Правило, "ПослеОбработки"));
				
			Иначе
				
				Выполнить(Правило.ПослеОбработки);
				
			КонецЕсли;
			
		Исключение
			
			ЗаписатьИнформациюОбОшибкеОбработчикаОчисткиДанных(28, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				Правило.Имя, "", "ПослеОбработкиПравилаОчистки");
			
		КонецПопытки;
		
	КонецЕсли;
	
КонецПроцедуры

// Обходит дерево правил очистки данных и выполняет очистку.
//
// Параметры:
//  Строки         - коллекция строк дерева значений.
// 
Процедура ОбработатьПравилаОчистки(Строки)
	
	Для каждого ПравилоОчистки Из Строки Цикл
		
		Если ПравилоОчистки.Включить = 0 Тогда
			
			Продолжить;
			
		КонецЕсли; 

		Если ПравилоОчистки.ЭтоГруппа Тогда
			
			ОбработатьПравилаОчистки(ПравилоОчистки.Строки);
			Продолжить;
			
		КонецЕсли;
		
		ОчиститьДанныеПоПравилу(ПравилоОчистки);
		
	КонецЦикла; 
	
КонецПроцедуры

#КонецОбласти

#Область ПроцедурыЗагрузкиДанных

// Устанавливает значение параметра "Загрузка" для свойства объекта "ОбменДанными".
//
// Параметры:
//  Объект   - объект, для которого устанавливается свойство.
//  Значение - значение устанавливаемого свойства "Загрузка".
// 
Процедура УстановитьОбменДаннымиЗагрузка(Объект, Значение = Истина) Экспорт
	
	Если Не ЗагружатьДанныеВРежимеОбмена Тогда
		Возврат;
	КонецЕсли;
	
	Если ЕстьРеквизитИлиСвойствоОбъекта(Объект, "ОбменДанными") Тогда
		СтруктураДляЗаполнения = Новый Структура("Загрузка", Значение);
		ЗаполнитьЗначенияСвойств(Объект.ОбменДанными, СтруктураДляЗаполнения);
	КонецЕсли;
	
КонецПроцедуры

Функция УстановитьСсылкуНового(Объект, Менеджер, СвойстваПоиска)
	
	УИ = СвойстваПоиска["{УникальныйИдентификатор}"];
	
	Если УИ <> Неопределено Тогда
		
		НоваяСсылка = Менеджер.ПолучитьСсылку(Новый УникальныйИдентификатор(УИ));
		
		Объект.УстановитьСсылкуНового(НоваяСсылка);
		
		СвойстваПоиска.Удалить("{УникальныйИдентификатор}");
		
	Иначе
		
		НоваяСсылка = Неопределено;
		
	КонецЕсли;
	
	Возврат НоваяСсылка;
	
КонецФункции

// Ищет объект по номеру в списке уже загруженных объектов.
//
// Параметры:
//   НПП - Число - номер искомого объекта в файле обмена.
//
// Возвращаемое значение:
//   - ЛюбаяСсылка - ссылка на найденный объект.
//   - Неопределено - если объект не найден.
// 
Функция НайтиОбъектПоНомеру(НПП, РежимПоискаОсновногоОбъекта = Ложь)

	Если НПП = 0 Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	СтруктураРезультата = ЗагруженныеОбъекты[НПП];
	
	Если СтруктураРезультата = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Если РежимПоискаОсновногоОбъекта И СтруктураРезультата.СсылкаФиктивная Тогда
		Возврат Неопределено;
	Иначе
		Возврат СтруктураРезультата.СсылкаНаОбъект;
	КонецЕсли; 

КонецФункции

Функция НайтиОбъектПоГлобальномуНомеру(НПП, РежимПоискаОсновногоОбъекта = Ложь)

	СтруктураРезультата = ЗагруженныеГлобальныеОбъекты[НПП];
	
	Если СтруктураРезультата = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Если РежимПоискаОсновногоОбъекта И СтруктураРезультата.СсылкаФиктивная Тогда
		Возврат Неопределено;
	Иначе
		Возврат СтруктураРезультата.СсылкаНаОбъект;
	КонецЕсли;
	
КонецФункции

Процедура ЗаписатьОбъектВИБ(Объект, Тип)
		
	Попытка
		
		УстановитьОбменДаннымиЗагрузка(Объект);
		Объект.Записать();
		
	Исключение
		
		СтрокаСообщенияОбОшибке = ЗаписатьИнформациюОбОшибкеВПротокол(26, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
			Объект, Тип);
		
		Если Не ФлагРежимОтладки Тогда
			ВызватьИсключение СтрокаСообщенияОбОшибке;
		КонецЕсли;
		
	КонецПопытки;
	
КонецПроцедуры

// Создает новый объект указанного типа, устанавливает реквизиты, указанные
// в структуре СвойстваПоиска.
//
// Параметры:
//  Тип - Тип - тип создаваемого объекта.
//  СвойстваПоиска - Структура - содержит устанавливаемые реквизиты нового объекта.
//
// Возвращаемое значение:
//   Произвольный - новый объект информационной базы.
// 
Функция СоздатьНовыйОбъект(Тип, СвойстваПоиска, Объект = Неопределено, 
	ЗаписыватьОбъектСразуПослеСоздания = Истина, НаборЗаписейРегистра = Неопределено,
	НоваяСсылка = Неопределено, НПП = 0, ГНПП = 0, ПараметрыОбъекта = Неопределено,
	УстанавливатьУОбъектаВсеСвойстваПоиска = Истина)

	СвойстваМД      = Менеджеры[Тип];
	ИмяТипа         = СвойстваМД.ИмяТипа;
	Менеджер        = СвойстваМД.Менеджер; // СправочникМенеджер, ДокументМенеджер, РегистрСведенийМенеджер, ПланСчетовМенеджер, ПланВидовРасчетаМенеджер, ПланОбменаМенеджер

	Если ИмяТипа = "Справочник"
		ИЛИ ИмяТипа = "ПланВидовХарактеристик" Тогда
		
		ЭтоГруппа = СвойстваПоиска["ЭтоГруппа"];
		
		Если ЭтоГруппа = Истина Тогда
			
			Объект = Менеджер.СоздатьГруппу();
						
		Иначе
			
			Объект = Менеджер.СоздатьЭлемент();
			
		КонецЕсли;		
				
	ИначеЕсли ИмяТипа = "Документ" Тогда
		
		Объект = Менеджер.СоздатьДокумент();
				
	ИначеЕсли ИмяТипа = "ПланСчетов" Тогда
		
		Объект = Менеджер.СоздатьСчет();
				
	ИначеЕсли ИмяТипа = "ПланВидовРасчета" Тогда
		
		Объект = Менеджер.СоздатьВидРасчета();
				
	ИначеЕсли ИмяТипа = "РегистрСведений" Тогда
		
		Если ЗаписыватьРегистрыНаборамиЗаписей Тогда
			
			НаборЗаписейРегистра = Менеджер.СоздатьНаборЗаписей();
			Объект = НаборЗаписейРегистра.Добавить();
			
		Иначе
			
			Объект = Менеджер.СоздатьМенеджерЗаписи();
						
		КонецЕсли;
		
		Возврат Объект;
		
	ИначеЕсли ИмяТипа = "ПланОбмена" Тогда
		
		Объект = Менеджер.СоздатьУзел();
				
	ИначеЕсли ИмяТипа = "Задача" Тогда
		
		Объект = Менеджер.СоздатьЗадачу();
		
	ИначеЕсли ИмяТипа = "БизнесПроцесс" Тогда
		
		Объект = Менеджер.СоздатьБизнесПроцесс();
		
	ИначеЕсли ИмяТипа = "Перечисление" Тогда
		
		Объект = СвойстваМД.ПустаяСсылка;	
		Возврат Объект;
		
	ИначеЕсли ИмяТипа = "ТочкаМаршрутаБизнесПроцесса" Тогда
		
		Возврат Неопределено;
				
	КонецЕсли;
	
	НоваяСсылка = УстановитьСсылкуНового(Объект, Менеджер, СвойстваПоиска);
	
	Если УстанавливатьУОбъектаВсеСвойстваПоиска Тогда
		УстановитьРеквизитыПоискаУОбъекта(Объект, СвойстваПоиска, Неопределено, Ложь, Ложь);
	КонецЕсли;
	
	// Проверки
	Если ИмяТипа = "Документ"
		ИЛИ ИмяТипа = "Задача"
		ИЛИ ИмяТипа = "БизнесПроцесс" Тогда
		
		Если НЕ ЗначениеЗаполнено(Объект.Дата) Тогда
			
			Объект.Дата = ТекущаяДатаСеанса();
			
		КонецЕсли;
		
	КонецЕсли;
		
	// Если Владелец не установлен, то нужно поле добавить
	// в возможные поля поиска, а в событии ПОЛЯПОИСКА указать поля без Владельца, если по нему поиск реально не нужен.
	
	Если ЗаписыватьОбъектСразуПослеСоздания Тогда
		
		Если НЕ ОбъектыПоСсылкеЗагружатьБезПометкиУдаления Тогда
			Объект.ПометкаУдаления = Истина;
		КонецЕсли;
		
		Если ГНПП <> 0
			ИЛИ Не ОптимизированнаяЗаписьОбъектов Тогда
		
			ЗаписатьОбъектВИБ(Объект, Тип);
			
		Иначе
			
			// Записывать объект сразу не будем, а только запомним что нужно записать
			// сохраним эту информацию в специальном стеке объектов для записи
			// вернем и новую ссылку и сам объект, хотя он еще не записан.
			Если НоваяСсылка = Неопределено Тогда
				
				// Самостоятельно генерируем новую ссылку.
				НовыйУникальныйИдентификатор = Новый УникальныйИдентификатор;
				НоваяСсылка = Менеджер.ПолучитьСсылку(НовыйУникальныйИдентификатор);
				Объект.УстановитьСсылкуНового(НоваяСсылка);
				
			КонецЕсли;
			
			ДополнитьСтекНеЗаписанныхОбъектов(НПП, ГНПП, Объект, НоваяСсылка, Тип, ПараметрыОбъекта);
			
			Возврат НоваяСсылка;
			
		КонецЕсли;
		
	Иначе
		
		Возврат Неопределено;
		
	КонецЕсли;
	
	Возврат Объект.Ссылка;
	
КонецФункции

// Читает из файла узел свойства объекта, устанавливает значение свойства.
//
// Параметры:
//  Тип - Тип - тип значения свойства.
//  ОбъектНайден - Булево - если после выполнения функции - Ложь, то значит
//                 объект свойства не найден в информационной базе и создан новый.
//
// Возвращаемое значение:
//   Произвольный - значение свойства.
// 
Функция ПрочитатьСвойство(Тип, ИмяПКО = "")
	
	Значение = Неопределено;
	НаличиеСвойств = Ложь;
	
	Пока ФайлОбмена.Прочитать() Цикл
		
		ИмяУзла = ФайлОбмена.ЛокальноеИмя;
		
		Если ИмяУзла = "Значение" Тогда
			
			ИскатьПоСвойству = одАтрибут(ФайлОбмена, одТипСтрока, "Свойство");
			Значение         = одЗначениеЭлемента(ФайлОбмена, Тип, ИскатьПоСвойству, ОбрезатьСтрокиСправа);
			НаличиеСвойств = Истина;
			
		ИначеЕсли ИмяУзла = "Ссылка" Тогда
			
			Значение       = НайтиОбъектПоСсылке(Тип, ИмяПКО);
			НаличиеСвойств = Истина;
			
		ИначеЕсли ИмяУзла = "Нпп" Тогда
			
			одПропустить(ФайлОбмена);
			
		ИначеЕсли ИмяУзла = "ГНпп" Тогда
			
			ФайлОбмена.Прочитать();
			ГНПП = Число(ФайлОбмена.Значение);
			Если ГНПП <> 0 Тогда
				Значение  = НайтиОбъектПоГлобальномуНомеру(ГНПП);
				НаличиеСвойств = Истина;
			КонецЕсли;
			
			ФайлОбмена.Прочитать();
			
		ИначеЕсли (ИмяУзла = "Свойство" ИЛИ ИмяУзла = "ЗначениеПараметра") И (ФайлОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			
			Если Не НаличиеСвойств
				И ЗначениеЗаполнено(Тип) Тогда
				
				// Если вообще ничего нет - значит пустое значение.
				Значение = одПолучитьПустоеЗначение(Тип);
				
			КонецЕсли;
			
			Прервать;
			
		ИначеЕсли ИмяУзла = "Выражение" Тогда
			
			Выражение = одЗначениеЭлемента(ФайлОбмена, одТипСтрока, , Ложь);
			Значение  = ВычислитьВыражение(Выражение);
			
			НаличиеСвойств = Истина;
			
		ИначеЕсли ИмяУзла = "Пусто" Тогда
			
			Значение = одПолучитьПустоеЗначение(Тип);
			НаличиеСвойств = Истина;		
			
		Иначе
			
			ЗаписатьВПротоколВыполнения(9);
			Прервать;
			
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат Значение;	
	
КонецФункции

Функция УстановитьРеквизитыПоискаУОбъекта(НайденныйОбъект, СвойстваПоиска, СвойстваПоискаНеЗамещать, 
	НужноСравниватьСТекущимиРеквизитами = Истина, НЕЗаменятьСвойстваНеПодлежащиеИзменению = Истина)
	
	ИзмененыРеквизитыОбъекта = Ложь;
				
	Для каждого Свойство Из СвойстваПоиска Цикл
					
		Имя      = Свойство.Ключ;
		Значение = Свойство.Значение;
		
		Если НЕЗаменятьСвойстваНеПодлежащиеИзменению
			И СвойстваПоискаНеЗамещать[Имя] <> Неопределено Тогда
			
			Продолжить;
			
		КонецЕсли;
					
		Если Имя = "ЭтоГруппа" 
			ИЛИ Имя = "{УникальныйИдентификатор}" 
			ИЛИ Имя = "{ИмяПредопределенногоЭлемента}" Тогда
						
			Продолжить;
						
		ИначеЕсли Имя = "ПометкаУдаления" Тогда
						
			Если НЕ НужноСравниватьСТекущимиРеквизитами
				ИЛИ НайденныйОбъект.ПометкаУдаления <> Значение Тогда
							
				НайденныйОбъект.ПометкаУдаления = Значение;
				ИзмененыРеквизитыОбъекта = Истина;
							
			КонецЕсли;
						
		Иначе
				
			// Отличные реквизиты устанавливаем.
			Если НайденныйОбъект[Имя] <> NULL Тогда
			
				Если НЕ НужноСравниватьСТекущимиРеквизитами
					ИЛИ НайденныйОбъект[Имя] <> Значение Тогда
						
					НайденныйОбъект[Имя] = Значение;
					ИзмененыРеквизитыОбъекта = Истина;
						
				КонецЕсли;
				
			КонецЕсли;
				
		КонецЕсли;
					
	КонецЦикла;
	
	Возврат ИзмененыРеквизитыОбъекта;
	
КонецФункции

Функция НайтиИлиСоздатьОбъектПоСвойству(СтруктураСвойств, ТипОбъекта, СвойстваПоиска, СвойстваПоискаНеЗамещать,
	ИмяТипаОбъекта, СвойствоПоиска, ЗначениеСвойстваПоиска, ОбъектНайден,
	СоздаватьНовыйЭлементЕслиНеНайден, НайденныйИлиСозданныйОбъект,
	РежимПоискаОсновногоОбъекта, СвойстваОбъектаМодифицированы, НПП, ГНПП,
	ПараметрыОбъекта, НоваяСсылкаУникальногоИдентификатора = Неопределено)
	
	ЭтоПеречисление = СтруктураСвойств.ИмяТипа = "Перечисление";
	
	Если ЭтоПеречисление Тогда
		
		СтрокаПоиска = "";
		
	Иначе
		
		СтрокаПоиска = СтруктураСвойств.СтрокаПоиска;
		
	КонецЕсли;
	
	Если РежимПоискаОсновногоОбъекта Или ПустаяСтрока(СтрокаПоиска) Тогда
		СтрокаЗапросаПоискаПоУникальномуИдентификатору = "";
	КонецЕсли;
	
	Объект = НайтиОбъектПоСвойству(СтруктураСвойств.Менеджер, СвойствоПоиска, ЗначениеСвойстваПоиска,
		НайденныйИлиСозданныйОбъект, , , СтрокаЗапросаПоискаПоУникальномуИдентификатору);
		
	ОбъектНайден = НЕ (Объект = Неопределено ИЛИ Объект.Пустая());
		
	Если Не ОбъектНайден Тогда
		Если СоздаватьНовыйЭлементЕслиНеНайден Тогда
		
			Объект = СоздатьНовыйОбъект(ТипОбъекта, СвойстваПоиска, НайденныйИлиСозданныйОбъект, 
				НЕ РежимПоискаОсновногоОбъекта,,НоваяСсылкаУникальногоИдентификатора, НПП, ГНПП, ПараметрыОбъекта);
				
			СвойстваОбъектаМодифицированы = Истина;
		КонецЕсли;
		Возврат Объект;
	
	КонецЕсли;
	
	Если ЭтоПеречисление Тогда
		Возврат Объект;
	КонецЕсли;			
	
	Если РежимПоискаОсновногоОбъекта Тогда
		
		Если НайденныйИлиСозданныйОбъект = Неопределено Тогда
			НайденныйИлиСозданныйОбъект = Объект.ПолучитьОбъект();
		КонецЕсли;
			
		СвойстваОбъектаМодифицированы = УстановитьРеквизитыПоискаУОбъекта(НайденныйИлиСозданныйОбъект, СвойстваПоиска, СвойстваПоискаНеЗамещать);
				
	КонецЕсли;
		
	Возврат Объект;
	
КонецФункции

Функция ПолучитьТипСвойства()
	
	СтроковыйТипСвойства = одАтрибут(ФайлОбмена, одТипСтрока, "Тип");
	Если ПустаяСтрока(СтроковыйТипСвойства) Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Возврат Тип(СтроковыйТипСвойства);
	
КонецФункции

Функция ПолучитьТипСвойстваПоДополнительнымДанным(ИнформацияОТипах, ИмяСвойства)
	
	ТипСвойства = ПолучитьТипСвойства();
				
	Если ТипСвойства = Неопределено
		И ИнформацияОТипах <> Неопределено Тогда
		
		ТипСвойства = ИнформацияОТипах[ИмяСвойства];
		
	КонецЕсли;
	
	Возврат ТипСвойства;
	
КонецФункции

Процедура ПрочитатьСвойстваПоискаИзФайла(СвойстваПоиска, СвойстваПоискаНеЗамещать, ИнформацияОТипах, 
	ПоискПоДатеНаРавенство = Ложь, ПараметрыОбъекта = Неопределено)
	
	ПоискПоДатеНаРавенство = Ложь;
	
	Пока ФайлОбмена.Прочитать() Цикл
		
		ИмяУзла = ФайлОбмена.ЛокальноеИмя;
				
		Если ИмяУзла = "Свойство"
			ИЛИ ИмяУзла = "ЗначениеПараметра" Тогда
					
			ЭтоПараметр = (ИмяУзла = "ЗначениеПараметра");
			
			Имя = одАтрибут(ФайлОбмена, одТипСтрока, "Имя");
			
			Если Имя = "{УникальныйИдентификатор}" 
				ИЛИ Имя = "{ИмяПредопределенногоЭлемента}" Тогда
				
				ТипСвойства = одТипСтрока;
				
			Иначе
			
				ТипСвойства = ПолучитьТипСвойстваПоДополнительнымДанным(ИнформацияОТипах, Имя);
			
			КонецЕсли;
			
			НеЗамещатьСвойство = одАтрибут(ФайлОбмена, одТипБулево, "НеЗамещать");
			ПоискПоДатеНаРавенство = ПоискПоДатеНаРавенство 
					ИЛИ одАтрибут(ФайлОбмена, одТипБулево, "ПоискПоДатеНаРавенство");
			//
			ИмяПКО = одАтрибут(ФайлОбмена, одТипСтрока, "ИмяПКО");
			
			ЗначениеСвойства = ПрочитатьСвойство(ТипСвойства, ИмяПКО);
			
			Если (Имя = "ЭтоГруппа") И (ЗначениеСвойства <> Истина) Тогда
				
				ЗначениеСвойства = Ложь;
												
			КонецЕсли;
			
			Если ЭтоПараметр Тогда
				
				
				ДобавитьПараметрПриНеобходимости(ПараметрыОбъекта, Имя, ЗначениеСвойства);
				
			Иначе
			
				СвойстваПоиска[Имя] = ЗначениеСвойства;
				
				Если НеЗамещатьСвойство Тогда
					
					СвойстваПоискаНеЗамещать[Имя] = Истина;
					
				КонецЕсли;
				
			КонецЕсли;
			
		ИначеЕсли (ИмяУзла = "Ссылка") И (ФайлОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			
			Прервать;
			
		Иначе
			
			ЗаписатьВПротоколВыполнения(9);
			Прервать;
			
		КонецЕсли;
		
	КонецЦикла;	
	
КонецПроцедуры

Функция ОпределитьУПоляНеограниченнаяДлина(МенеджерТипа, ИмяПараметра)
	
	ДлинныеСтроки = Неопределено;
	Если НЕ МенеджерТипа.Свойство("ДлинныеСтроки", ДлинныеСтроки) Тогда
		
		ДлинныеСтроки = Новый Соответствие;
		Для Каждого Реквизит Из МенеджерТипа.ОбъектМД.Реквизиты Цикл
			
			Если Реквизит.Тип.СодержитТип(одТипСтрока) 
				И (Реквизит.Тип.КвалификаторыСтроки.Длина = 0) Тогда
				
				ДлинныеСтроки.Вставить(Реквизит.Имя, Реквизит.Имя);	
				
			КонецЕсли;
			
		КонецЦикла;
		
		МенеджерТипа.Вставить("ДлинныеСтроки", ДлинныеСтроки);
		
	КонецЕсли;
	
	Возврат (ДлинныеСтроки[ИмяПараметра] <> Неопределено);
		
КонецФункции

Функция ОпределитьЭтотПараметрНеограниченнойДлинны(МенеджерТипа, ЗначениеПараметра, ИмяПараметра)
	
	Попытка
			
		Если ТипЗнч(ЗначениеПараметра) = одТипСтрока Тогда
			СтрокаНеограниченнойДлины = ОпределитьУПоляНеограниченнаяДлина(МенеджерТипа, ИмяПараметра);
		Иначе
			СтрокаНеограниченнойДлины = Ложь;
		КонецЕсли;		
												
	Исключение
				
		СтрокаНеограниченнойДлины = Ложь;
				
	КонецПопытки;
	
	Возврат СтрокаНеограниченнойДлины;	
	
КонецФункции

Функция НайтиЭлементЗапросом(СтруктураСвойств, СвойстваПоиска, ТипОбъекта = Неопределено, 
	МенеджерТипа = Неопределено, КоличествоРеальныхСвойствДляПоиска = Неопределено)
	
	КоличествоСвойствДляПоиска = ?(КоличествоРеальныхСвойствДляПоиска = Неопределено, СвойстваПоиска.Количество(), КоличествоРеальныхСвойствДляПоиска);
	
	Если КоличествоСвойствДляПоиска = 0
		И СтруктураСвойств.ИмяТипа = "Перечисление" Тогда
		
		Возврат СтруктураСвойств.ПустаяСсылка;
		
	КонецЕсли;	
	
	ТекстЗапроса       = СтруктураСвойств.СтрокаПоиска;
	
	Если ПустаяСтрока(ТекстЗапроса) Тогда
		Возврат СтруктураСвойств.ПустаяСсылка;
	КонецЕсли;
	
	ЗапросПоиска       = Новый Запрос();
	КоличествоСвойствПоКоторымУстановленПоиск = 0;
			
	Для каждого Свойство Из СвойстваПоиска Цикл
				
		ИмяПараметра      = Свойство.Ключ;
		
		// Не по всем параметрам можно искать.
		Если ИмяПараметра = "{УникальныйИдентификатор}"
			ИЛИ ИмяПараметра = "{ИмяПредопределенногоЭлемента}" Тогда
						
			Продолжить;
						
		КонецЕсли;
		
		ЗначениеПараметра = Свойство.Значение;
		ЗапросПоиска.УстановитьПараметр(ИмяПараметра, ЗначениеПараметра);
				
		Попытка
			
			СтрокаНеограниченнойДлины = ОпределитьЭтотПараметрНеограниченнойДлинны(СтруктураСвойств, ЗначениеПараметра, ИмяПараметра);		
													
		Исключение
					
			СтрокаНеограниченнойДлины = Ложь;
					
		КонецПопытки;
		
		КоличествоСвойствПоКоторымУстановленПоиск = КоличествоСвойствПоКоторымУстановленПоиск + 1;
				
		Если СтрокаНеограниченнойДлины Тогда
					
			ТекстЗапроса = ТекстЗапроса + ?(КоличествоСвойствПоКоторымУстановленПоиск > 1, " И ", "") + ИмяПараметра + " ПОДОБНО &" + ИмяПараметра;
					
		Иначе
					
			ТекстЗапроса = ТекстЗапроса + ?(КоличествоСвойствПоКоторымУстановленПоиск > 1, " И ", "") + ИмяПараметра + " = &" + ИмяПараметра;
					
		КонецЕсли;
								
	КонецЦикла;
	
	Если КоличествоСвойствПоКоторымУстановленПоиск = 0 Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	ЗапросПоиска.Текст = ТекстЗапроса;
	Результат = ЗапросПоиска.Выполнить();
			
	Если Результат.Пустой() Тогда
		
		Возврат Неопределено;
								
	Иначе
		
		// Возвращаем первый найденный объект.
		Выборка = Результат.Выбрать();
		Выборка.Следующий();
		СсылкаНаОбъект = Выборка.Ссылка;
				
	КонецЕсли;
	
	Возврат СсылкаНаОбъект;
	
КонецФункции

Функция ОпределитьПоТипуОбъектаИспользоватьДополнительныйПоискПоПолямПоиска(ТипСсылкиСтрокой)
	
	ЗначениеСоответствия = мСоответствиеДопПараметровПоиска.Получить(ТипСсылкиСтрокой);
	
	Если ЗначениеСоответствия <> Неопределено Тогда
		Возврат ЗначениеСоответствия;
	КонецЕсли;
	
	Попытка
	
		Для Каждого Элемент Из Правила Цикл
			
			Если Элемент.Значение.Приемник = ТипСсылкиСтрокой Тогда
				
				Если Элемент.Значение.СинхронизироватьПоИдентификатору = Истина Тогда
					
					НужноПродолжитьПоиск = (Элемент.Значение.ПродолжитьПоискПоПолямПоискаЕслиПоИдентификаторуНеНашли = Истина);
					мСоответствиеДопПараметровПоиска.Вставить(ТипСсылкиСтрокой, НужноПродолжитьПоиск);
					
					Возврат НужноПродолжитьПоиск;
					
				КонецЕсли;
				
			КонецЕсли;
			
		КонецЦикла;
		
		мСоответствиеДопПараметровПоиска.Вставить(ТипСсылкиСтрокой, Ложь);
		Возврат Ложь;
	
	Исключение
		
		мСоответствиеДопПараметровПоиска.Вставить(ТипСсылкиСтрокой, Ложь);
		Возврат Ложь;
	
    КонецПопытки;
	
КонецФункции

// Определяет по типу объекта приемника правило конвертации объекта (ПКО).
//
// Параметры:
//  ТипСсылкиСтрокой - Строка - тип объекта в строковом представлении, например, "СправочникСсылка.Номенклатура".
// 
// Возвращаемое значение:
//  ЗначениеСоответствия = Правило конвертации объекта.
// 
Функция ОпределитьПоТипуОбъектаПриемникаПравилоКонвертацииКотороеСодержитАлгоритмПоиска(ТипСсылкиСтрокой)
	
	ЗначениеСоответствия = мСоответствиеПравилКонвертации.Получить(ТипСсылкиСтрокой);
	
	Если ЗначениеСоответствия <> Неопределено Тогда
		Возврат ЗначениеСоответствия;
	КонецЕсли;
	
	Попытка
	
		Для Каждого Элемент Из Правила Цикл
			
			Если Элемент.Значение.Приемник = ТипСсылкиСтрокой Тогда
				
				Если Элемент.Значение.ЕстьОбработчикПоследовательностьПолейПоиска = Истина Тогда
					
					Правило = Элемент.Значение;
					
					мСоответствиеПравилКонвертации.Вставить(ТипСсылкиСтрокой, Правило);
					
					Возврат Правило;
					
				КонецЕсли;
				
			КонецЕсли;
			
		КонецЦикла;
		
		мСоответствиеПравилКонвертации.Вставить(ТипСсылкиСтрокой, Неопределено);
		Возврат Неопределено;
	
	Исключение
		
		мСоответствиеПравилКонвертации.Вставить(ТипСсылкиСтрокой, Неопределено);
		Возврат Неопределено;
	
	КонецПопытки;
	
КонецФункции

Функция НайтиСсылкуНаОбъектПоОдномуСвойству(СвойстваПоиска, СтруктураСвойств)
	
	Для каждого Свойство Из СвойстваПоиска Цикл
					
		ИмяПараметра      = Свойство.Ключ;
					
		// Не по всем параметрам можно искать.
		Если ИмяПараметра = "{УникальныйИдентификатор}"
			ИЛИ ИмяПараметра = "{ИмяПредопределенногоЭлемента}" Тогда
						
			Продолжить;
						
		КонецЕсли;
					
		ЗначениеПараметра = Свойство.Значение;
		СсылкаНаОбъект = НайтиОбъектПоСвойству(СтруктураСвойств.Менеджер, ИмяПараметра, ЗначениеПараметра, Неопределено, СтруктураСвойств, СвойстваПоиска);
		
	КонецЦикла;
	
	Возврат СсылкаНаОбъект;
	
КонецФункции

Функция НайтиСсылкуНаДокумент(СвойстваПоиска, СтруктураСвойств, КоличествоРеальныхСвойствДляПоиска, ИскатьЗапросом, ПоискПоДатеНаРавенство)
	
	// Попробуем документ по дате и номеру найти.
	ИскатьЗапросом = ПоискПоДатеНаРавенство ИЛИ (КоличествоРеальныхСвойствДляПоиска <> 2);
				
	Если ИскатьЗапросом Тогда
		Возврат Неопределено;
	КонецЕсли;
					
	НомерДокумента = СвойстваПоиска["Номер"];
	ДатаДокумента  = СвойстваПоиска["Дата"];
					
	Если (НомерДокумента <> Неопределено) И (ДатаДокумента <> Неопределено) Тогда
						
		СсылкаНаОбъект = СтруктураСвойств.Менеджер.НайтиПоНомеру(НомерДокумента, ДатаДокумента);
																		
	Иначе
						
		// По дате и номеру найти не удалось - надо искать запросом.
		ИскатьЗапросом = Истина;
		СсылкаНаОбъект = Неопределено;
						
	КонецЕсли;
	
	Возврат СсылкаНаОбъект;
	
КонецФункции

Функция НайтиСсылкуНаСправочник(СвойстваПоиска, СтруктураСвойств, КоличествоРеальныхСвойствДляПоиска, ИскатьЗапросом)
	
	Владелец     = СвойстваПоиска["Владелец"];
	Родитель     = СвойстваПоиска["Родитель"];
	Код          = СвойстваПоиска["Код"];
	Наименование = СвойстваПоиска["Наименование"];
				
	Кол          = 0;
				
	Если Владелец <> Неопределено Тогда	Кол = 1 + Кол; КонецЕсли;
	Если Родитель <> Неопределено Тогда	Кол = 1 + Кол; КонецЕсли;
	Если Код <> Неопределено Тогда Кол = 1 + Кол; КонецЕсли;
	Если Наименование <> Неопределено Тогда	Кол = 1 + Кол; КонецЕсли;
				
	ИскатьЗапросом = (Кол <> КоличествоРеальныхСвойствДляПоиска);
				
	Если ИскатьЗапросом Тогда
		Возврат Неопределено;
	КонецЕсли;
					
	Если (Код <> Неопределено) И (Наименование = Неопределено) Тогда
						
		СсылкаНаОбъект = СтруктураСвойств.Менеджер.НайтиПоКоду(Код, , Родитель, Владелец);
																		
	ИначеЕсли (Код = Неопределено) И (Наименование <> Неопределено) Тогда
						
		СсылкаНаОбъект = СтруктураСвойств.Менеджер.НайтиПоНаименованию(Наименование, ИСТИНА, Родитель, Владелец);
											
	Иначе
						
		ИскатьЗапросом = Истина;
		СсылкаНаОбъект = Неопределено;
						
	КонецЕсли;
															
	Возврат СсылкаНаОбъект;
	
КонецФункции

Функция НайтиСсылкуНаПВХ(СвойстваПоиска, СтруктураСвойств, КоличествоРеальныхСвойствДляПоиска, ИскатьЗапросом)
	
	Родитель     = СвойстваПоиска["Родитель"];
	Код          = СвойстваПоиска["Код"];
	Наименование = СвойстваПоиска["Наименование"];
	Кол          = 0;
				
	Если Родитель     <> Неопределено Тогда	Кол = 1 + Кол КонецЕсли;
	Если Код          <> Неопределено Тогда Кол = 1 + Кол КонецЕсли;
	Если Наименование <> Неопределено Тогда	Кол = 1 + Кол КонецЕсли;
				
	ИскатьЗапросом = (Кол <> КоличествоРеальныхСвойствДляПоиска);
				
	Если ИскатьЗапросом Тогда
		Возврат Неопределено;
	КонецЕсли;
					
	Если     (Код <> Неопределено) И (Наименование = Неопределено) Тогда
						
		СсылкаНаОбъект = СтруктураСвойств.Менеджер.НайтиПоКоду(Код, Родитель);
												
	ИначеЕсли (Код = Неопределено) И (Наименование <> Неопределено) Тогда
						
		СсылкаНаОбъект = СтруктураСвойств.Менеджер.НайтиПоНаименованию(Наименование, ИСТИНА, Родитель);
																	
	Иначе
						
		ИскатьЗапросом = Истина;
		СсылкаНаОбъект = Неопределено;
			
	КонецЕсли;
															
	Возврат СсылкаНаОбъект;
	
КонецФункции

Функция НайтиСсылкуНаПланОбмена(СвойстваПоиска, СтруктураСвойств, КоличествоРеальныхСвойствДляПоиска, ИскатьЗапросом)
	
	Код          = СвойстваПоиска["Код"];
	Наименование = СвойстваПоиска["Наименование"];
	Кол          = 0;
				
	Если Код          <> Неопределено Тогда Кол = 1 + Кол КонецЕсли;
	Если Наименование <> Неопределено Тогда	Кол = 1 + Кол КонецЕсли;
				
	ИскатьЗапросом = (Кол <> КоличествоРеальныхСвойствДляПоиска);
				
	Если ИскатьЗапросом Тогда
		Возврат Неопределено;
	КонецЕсли;
					
	Если     (Код <> Неопределено) И (Наименование = Неопределено) Тогда
						
		СсылкаНаОбъект = СтруктураСвойств.Менеджер.НайтиПоКоду(Код);
												
	ИначеЕсли (Код = Неопределено) И (Наименование <> Неопределено) Тогда
						
		СсылкаНаОбъект = СтруктураСвойств.Менеджер.НайтиПоНаименованию(Наименование, ИСТИНА);
																	
	Иначе
						
		ИскатьЗапросом = Истина;
		СсылкаНаОбъект = Неопределено;
						
	КонецЕсли;
															
	Возврат СсылкаНаОбъект;
	
КонецФункции

Функция НайтиСсылкуНаЗадачу(СвойстваПоиска, СтруктураСвойств, КоличествоРеальныхСвойствДляПоиска, ИскатьЗапросом)
	
	Код          = СвойстваПоиска["Номер"];
	Наименование = СвойстваПоиска["Наименование"];
	Кол          = 0;
				
	Если Код          <> Неопределено Тогда Кол = 1 + Кол КонецЕсли;
	Если Наименование <> Неопределено Тогда	Кол = 1 + Кол КонецЕсли;
				
	ИскатьЗапросом = (Кол <> КоличествоРеальныхСвойствДляПоиска);
				
	Если ИскатьЗапросом Тогда
		Возврат Неопределено;
	КонецЕсли;
	
					
	Если     (Код <> Неопределено) И (Наименование = Неопределено) Тогда
						
		СсылкаНаОбъект = СтруктураСвойств.Менеджер.НайтиПоНомеру(Код);
												
	ИначеЕсли (Код = Неопределено) И (Наименование <> Неопределено) Тогда
						
		СсылкаНаОбъект = СтруктураСвойств.Менеджер.НайтиПоНаименованию(Наименование, ИСТИНА);
																	
	Иначе
						
		ИскатьЗапросом = Истина;
		СсылкаНаОбъект = Неопределено;
						
	КонецЕсли;
															
	Возврат СсылкаНаОбъект;
	
КонецФункции

Функция НайтиСсылкуНаБизнесПроцесс(СвойстваПоиска, СтруктураСвойств, КоличествоРеальныхСвойствДляПоиска, ИскатьЗапросом)
	
	Код          = СвойстваПоиска["Номер"];
	Кол          = 0;
				
	Если Код <> Неопределено Тогда Кол = 1 + Кол КонецЕсли;
								
	ИскатьЗапросом = (Кол <> КоличествоРеальныхСвойствДляПоиска);
				
	Если ИскатьЗапросом Тогда
		Возврат Неопределено;
	КонецЕсли;
					
	Если  (Код <> Неопределено) Тогда
						
		СсылкаНаОбъект = СтруктураСвойств.Менеджер.НайтиПоНомеру(Код);
												
	Иначе
						
		ИскатьЗапросом = Истина;
		СсылкаНаОбъект = Неопределено;
						
	КонецЕсли;
															
	Возврат СсылкаНаОбъект;
	
КонецФункции

Процедура ДобавитьСсылкуВСписокЗагруженныхОбъектов(ГНППСсылки, НППСсылки, СсылкаНаОбъект, СсылкаФиктивная = Ложь)
	
	// Запоминаем ссылку на объект.
	Если НЕ ЗапоминатьЗагруженныеОбъекты 
		ИЛИ СсылкаНаОбъект = Неопределено Тогда
		
		Возврат;
		
	КонецЕсли;
	
	СтруктураЗаписи = Новый Структура("СсылкаНаОбъект, СсылкаФиктивная", СсылкаНаОбъект, СсылкаФиктивная);
	
	// Запоминаем ссылку на объект.
	Если ГНППСсылки <> 0 Тогда
		
		ЗагруженныеГлобальныеОбъекты[ГНППСсылки] = СтруктураЗаписи;
		
	ИначеЕсли НППСсылки <> 0 Тогда
		
		ЗагруженныеОбъекты[НППСсылки] = СтруктураЗаписи;
						
	КонецЕсли;	
	
КонецПроцедуры

Функция НайтиЭлементПоСвойствамПоиска(ТипОбъекта, ИмяТипаОбъекта, СвойстваПоиска, 
	СтруктураСвойств, СтрокаИменСвойствПоиска, ПоискПоДатеНаРавенство)
	
	// Не нужно искать по имени предопределенного элемента и по уникальной ссылке на объект
	// нужно искать только по тем свойствам, которые имеются в строке имен свойств. Если там пусто, то по
	// всем имеющимся свойствам поиска.
		
	ИскатьЗапросом = Ложь;	
	
	Если ПустаяСтрока(СтрокаИменСвойствПоиска) Тогда
		
		ВременныеСвойстваПоиска = СвойстваПоиска;
		
	Иначе
		
		ВыбранныеСвойства = СтрРазделить(СтрокаИменСвойствПоиска, ", ", Ложь);
		
		ВременныеСвойстваПоиска = Новый Соответствие;
		Для Каждого ЭлементСвойств Из СвойстваПоиска Цикл
			
			Если ВыбранныеСвойства.Найти(ЭлементСвойств.Ключ) <> Неопределено Тогда
				ВременныеСвойстваПоиска.Вставить(ЭлементСвойств.Ключ, ЭлементСвойств.Значение);
			КонецЕсли;
			
		КонецЦикла;
		
	КонецЕсли;
	
	СвойствоУникальныйИдентификатор = ВременныеСвойстваПоиска["{УникальныйИдентификатор}"];
	СвойствоИмяПредопределенного = ВременныеСвойстваПоиска["{ИмяПредопределенногоЭлемента}"];
	
	КоличествоРеальныхСвойствДляПоиска = ВременныеСвойстваПоиска.Количество();
	КоличествоРеальныхСвойствДляПоиска = КоличествоРеальныхСвойствДляПоиска - ?(СвойствоУникальныйИдентификатор <> Неопределено, 1, 0);
	КоличествоРеальныхСвойствДляПоиска = КоличествоРеальныхСвойствДляПоиска - ?(СвойствоИмяПредопределенного <> Неопределено, 1, 0);
	
	
	Если КоличествоРеальныхСвойствДляПоиска = 1 Тогда
				
		СсылкаНаОбъект = НайтиСсылкуНаОбъектПоОдномуСвойству(ВременныеСвойстваПоиска, СтруктураСвойств);
																						
	ИначеЕсли ИмяТипаОбъекта = "Документ" Тогда
				
		СсылкаНаОбъект = НайтиСсылкуНаДокумент(ВременныеСвойстваПоиска, СтруктураСвойств, КоличествоРеальныхСвойствДляПоиска, ИскатьЗапросом, ПоискПоДатеНаРавенство);
											
	ИначеЕсли ИмяТипаОбъекта = "Справочник" Тогда
				
		СсылкаНаОбъект = НайтиСсылкуНаСправочник(ВременныеСвойстваПоиска, СтруктураСвойств, КоличествоРеальныхСвойствДляПоиска, ИскатьЗапросом);
								
	ИначеЕсли ИмяТипаОбъекта = "ПланВидовХарактеристик" Тогда
				
		СсылкаНаОбъект = НайтиСсылкуНаПВХ(ВременныеСвойстваПоиска, СтруктураСвойств, КоличествоРеальныхСвойствДляПоиска, ИскатьЗапросом);
							
	ИначеЕсли ИмяТипаОбъекта = "ПланОбмена" Тогда
				
		СсылкаНаОбъект = НайтиСсылкуНаПланОбмена(ВременныеСвойстваПоиска, СтруктураСвойств, КоличествоРеальныхСвойствДляПоиска, ИскатьЗапросом);
							
	ИначеЕсли ИмяТипаОбъекта = "Задача" Тогда
				
		СсылкаНаОбъект = НайтиСсылкуНаЗадачу(ВременныеСвойстваПоиска, СтруктураСвойств, КоличествоРеальныхСвойствДляПоиска, ИскатьЗапросом);
												
	ИначеЕсли ИмяТипаОбъекта = "БизнесПроцесс" Тогда
				
		СсылкаНаОбъект = НайтиСсылкуНаБизнесПроцесс(ВременныеСвойстваПоиска, СтруктураСвойств, КоличествоРеальныхСвойствДляПоиска, ИскатьЗапросом);
									
	Иначе
				
		ИскатьЗапросом = Истина;
				
	КонецЕсли;
		
	Если ИскатьЗапросом Тогда
			
		СсылкаНаОбъект = НайтиЭлементЗапросом(СтруктураСвойств, ВременныеСвойстваПоиска, ТипОбъекта, , КоличествоРеальныхСвойствДляПоиска);
				
	КонецЕсли;
	
	Возврат СсылкаНаОбъект;
	
КонецФункции

Процедура ОбработатьУстановкуСвойствПоискаУОбъекта(УстанавливатьУОбъектаВсеСвойстваПоиска, ТипОбъекта, СвойстваПоиска, 
	СвойстваПоискаНеЗамещать, СсылкаНаОбъект, СозданныйОбъект, ЗаписыватьНовыйОбъектВИнформационнуюБазу = Истина, ИзмененыРеквизитыОбъекта = Ложь)
	
	Если УстанавливатьУОбъектаВсеСвойстваПоиска <> Истина Тогда
		Возврат;
	КонецЕсли;
	
	Если Не ЗначениеЗаполнено(СсылкаНаОбъект) Тогда
		Возврат;
	КонецЕсли;
	
	Если СозданныйОбъект = Неопределено Тогда
		СозданныйОбъект = СсылкаНаОбъект.ПолучитьОбъект();
	КонецЕсли;
	
	ИзмененыРеквизитыОбъекта = УстановитьРеквизитыПоискаУОбъекта(СозданныйОбъект, СвойстваПоиска, СвойстваПоискаНеЗамещать);
	
	// Если было то что изменено, тогда перезаписываем объект.
	Если ИзмененыРеквизитыОбъекта
		И ЗаписыватьНовыйОбъектВИнформационнуюБазу Тогда
		
		ЗаписатьОбъектВИБ(СозданныйОбъект, ТипОбъекта);
		
	КонецЕсли;
	
КонецПроцедуры

Функция ОбработатьПоискОбъектаПоСтруктуре(НомерОбъекта, ТипОбъекта, СозданныйОбъект,
	РежимПоискаОсновногоОбъекта, СвойстваОбъектаМодифицированы, ОбъектНайден,
	ЭтоГлобальныйНомер, ПараметрыОбъекта)
	
	СтруктураДанных = мГлобальныйСтекНеЗаписанныхОбъектов[НомерОбъекта];
	
	Если СтруктураДанных <> Неопределено Тогда
		
		СвойстваОбъектаМодифицированы = Истина;
		СозданныйОбъект = СтруктураДанных.Объект;
		
		Если СтруктураДанных.ИзвестнаяСсылка = Неопределено Тогда
			
			УстановитьСсылкуДляОбъекта(СтруктураДанных);
			
		КонецЕсли;
			
		СсылкаНаОбъект = СтруктураДанных.ИзвестнаяСсылка;
		ПараметрыОбъекта = СтруктураДанных.ПараметрыОбъекта;
		
		ОбъектНайден = Ложь;
		
	Иначе
		
		СозданныйОбъект = Неопределено;
		
		Если ЭтоГлобальныйНомер Тогда
			СсылкаНаОбъект = НайтиОбъектПоГлобальномуНомеру(НомерОбъекта, РежимПоискаОсновногоОбъекта);
		Иначе
			СсылкаНаОбъект = НайтиОбъектПоНомеру(НомерОбъекта, РежимПоискаОсновногоОбъекта);
		КонецЕсли;
		
	КонецЕсли;
	
	Если СсылкаНаОбъект <> Неопределено Тогда
		
		Если РежимПоискаОсновногоОбъекта Тогда
			
			СвойстваПоиска = "";
			СвойстваПоискаНеЗамещать = "";
			ПрочитатьИнформациюОСвойствахПоиска(ТипОбъекта, СвойстваПоиска, СвойстваПоискаНеЗамещать, , ПараметрыОбъекта);
			
			// Для основного поиска нужно поля поиска еще раз проверить, возможно нужно их переустановить...
			Если СозданныйОбъект = Неопределено Тогда
				
				СозданныйОбъект = СсылкаНаОбъект.ПолучитьОбъект();
				
			КонецЕсли;
			
			СвойстваОбъектаМодифицированы = УстановитьРеквизитыПоискаУОбъекта(СозданныйОбъект, СвойстваПоиска, СвойстваПоискаНеЗамещать);
			
		Иначе
			
			одПропустить(ФайлОбмена);
			
		КонецЕсли;
		
		Возврат СсылкаНаОбъект;
		
	КонецЕсли;
	
	Возврат Неопределено;
	
КонецФункции

Процедура ПрочитатьИнформациюОСвойствахПоиска(ТипОбъекта, СвойстваПоиска, СвойстваПоискаНеЗамещать, 
	ПоискПоДатеНаРавенство = Ложь, ПараметрыОбъекта = Неопределено)
	
	Если СвойстваПоиска = "" Тогда
		СвойстваПоиска = Новый Соответствие;		
	КонецЕсли;
	
	Если СвойстваПоискаНеЗамещать = "" Тогда
		СвойстваПоискаНеЗамещать = Новый Соответствие;		
	КонецЕсли;	
	
	ИнформацияОТипах = мСоответствиеТиповДанныхДляЗагрузки[ТипОбъекта];
	ПрочитатьСвойстваПоискаИзФайла(СвойстваПоиска, СвойстваПоискаНеЗамещать, ИнформацияОТипах, ПоискПоДатеНаРавенство, ПараметрыОбъекта);	
	
КонецПроцедуры

// Производит поиск объекта в информационной базе, если не найден создает новый.
//
// Параметры:
//  ТипОбъекта     - тип искомого объекта.
//  СвойстваПоиска - Структура - содержащая свойства по которым производится поиск объекта.
//  ОбъектНайден   - если Ложь, то объект не найден, а создан новый.
//
// Возвращаемое значение:
//  Новый или найденный объект информационной базы.
//  
Функция НайтиОбъектПоСсылке(ТипОбъекта,
							ИмяПКО = "",
							СвойстваПоиска = "", 
							СвойстваПоискаНеЗамещать = "", 
							ОбъектНайден = Истина, 
							СозданныйОбъект = Неопределено, 
							НеСоздаватьОбъектЕслиНеНайден = Неопределено,
							РежимПоискаОсновногоОбъекта = Ложь, 
							СвойстваОбъектаМодифицированы = Ложь,
							НППГлобальнойСсылки = 0,
							НППСсылки = 0,
							ИзвестнаяСсылкаУникальногоИдентификатора = Неопределено,
							ПараметрыОбъекта = Неопределено)

	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	ПоискПоДатеНаРавенство = Ложь;
	СсылкаНаОбъект = Неопределено;
	СтруктураСвойств = Неопределено;
	ИмяТипаОбъекта = Неопределено;
	СсылкаНаОбъектФиктивная = Ложь;
	ПКО = Неопределено;
	АлгоритмПоиска = "";
	
	Если ЗапоминатьЗагруженныеОбъекты Тогда
		
		// Есть номер по порядку из файла - по нему и ищем.
		НППГлобальнойСсылки = одАтрибут(ФайлОбмена, одТипЧисло, "ГНпп");
		
		Если НППГлобальнойСсылки <> 0 Тогда
			
			СсылкаНаОбъект = ОбработатьПоискОбъектаПоСтруктуре(НППГлобальнойСсылки, ТипОбъекта, СозданныйОбъект,
				РежимПоискаОсновногоОбъекта, СвойстваОбъектаМодифицированы, ОбъектНайден, Истина, ПараметрыОбъекта);
			
			Если СсылкаНаОбъект <> Неопределено Тогда
				Возврат СсылкаНаОбъект;
			КонецЕсли;
			
		КонецЕсли;
		
		// Есть номер по порядку из файла - по нему и ищем.
		НППСсылки = одАтрибут(ФайлОбмена, одТипЧисло, "Нпп");
		
		Если НППСсылки <> 0 Тогда
		
			СсылкаНаОбъект = ОбработатьПоискОбъектаПоСтруктуре(НППСсылки, ТипОбъекта, СозданныйОбъект,
				РежимПоискаОсновногоОбъекта, СвойстваОбъектаМодифицированы, ОбъектНайден, Ложь, ПараметрыОбъекта);
				
			Если СсылкаНаОбъект <> Неопределено Тогда
				Возврат СсылкаНаОбъект;
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЕсли;
	
	НеСоздаватьОбъектЕслиНеНайден = одАтрибут(ФайлОбмена, одТипБулево, "НеСоздаватьЕслиНеНайден");
	ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD = НЕ РежимПоискаОсновногоОбъекта 
		И одАтрибут(ФайлОбмена, одТипБулево, "ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD");
	
	// Создаем свойства поиска объектов.
	ПрочитатьИнформациюОСвойствахПоиска(ТипОбъекта, СвойстваПоиска, СвойстваПоискаНеЗамещать, ПоискПоДатеНаРавенство, ПараметрыОбъекта);
		
	СозданныйОбъект = Неопределено;
	
	Если Не ОбъектНайден Тогда
		
		СсылкаНаОбъект = СоздатьНовыйОбъект(ТипОбъекта, СвойстваПоиска, СозданныйОбъект, , , , НППСсылки, НППГлобальнойСсылки);
		ДобавитьСсылкуВСписокЗагруженныхОбъектов(НППГлобальнойСсылки, НППСсылки, СсылкаНаОбъект);
		Возврат СсылкаНаОбъект;
		
	КонецЕсли;	
		
	СтруктураСвойств   = Менеджеры[ТипОбъекта];
	ИмяТипаОбъекта     = СтруктураСвойств.ИмяТипа;
		
	СвойствоУникальныйИдентификатор = СвойстваПоиска["{УникальныйИдентификатор}"];
	СвойствоИмяПредопределенного = СвойстваПоиска["{ИмяПредопределенногоЭлемента}"];
	
	ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD = ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD
		И СвойствоУникальныйИдентификатор <> Неопределено;
		
	// Если это предопределенный элемент ищем по имени.
	Если СвойствоИмяПредопределенного <> Неопределено Тогда
		
		АвтоматическиСоздаватьНовыйОбъект = НЕ НеСоздаватьОбъектЕслиНеНайден
			И НЕ ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD;
		
		СсылкаНаОбъект = НайтиИлиСоздатьОбъектПоСвойству(СтруктураСвойств, ТипОбъекта, СвойстваПоиска, СвойстваПоискаНеЗамещать,
			ИмяТипаОбъекта, "{ИмяПредопределенногоЭлемента}", СвойствоИмяПредопределенного, ОбъектНайден, 
			АвтоматическиСоздаватьНовыйОбъект, СозданныйОбъект, РежимПоискаОсновногоОбъекта, СвойстваОбъектаМодифицированы,
			НППСсылки, НППГлобальнойСсылки, ПараметрыОбъекта);
			
	ИначеЕсли (СвойствоУникальныйИдентификатор <> Неопределено) Тогда
			
		// Не всегда нужно по уникальному идентификатору новый элемент создавать, возможно нужно продолжить поиск.
		НужноПродолжитьПоискЕслиЭлементПоGUIDНеНайден = ОпределитьПоТипуОбъектаИспользоватьДополнительныйПоискПоПолямПоиска(СтруктураСвойств.ТипСсылкиСтрокой);
		
		АвтоматическиСоздаватьНовыйОбъект = (НЕ НеСоздаватьОбъектЕслиНеНайден
			И НЕ НужноПродолжитьПоискЕслиЭлементПоGUIDНеНайден)
			И НЕ ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD;
			
		СсылкаНаОбъект = НайтиИлиСоздатьОбъектПоСвойству(СтруктураСвойств, ТипОбъекта, СвойстваПоиска, СвойстваПоискаНеЗамещать,
			ИмяТипаОбъекта, "{УникальныйИдентификатор}", СвойствоУникальныйИдентификатор, ОбъектНайден, 
			АвтоматическиСоздаватьНовыйОбъект, СозданныйОбъект, 
			РежимПоискаОсновногоОбъекта, СвойстваОбъектаМодифицированы,
			НППСсылки, НППГлобальнойСсылки, ПараметрыОбъекта, ИзвестнаяСсылкаУникальногоИдентификатора);
			
		Если Не НужноПродолжитьПоискЕслиЭлементПоGUIDНеНайден Тогда

			Если Не ЗначениеЗаполнено(СсылкаНаОбъект)
				И ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD Тогда
				
				СсылкаНаОбъект = СтруктураСвойств.Менеджер.ПолучитьСсылку(Новый УникальныйИдентификатор(СвойствоУникальныйИдентификатор));
				ОбъектНайден = Ложь;
				СсылкаНаОбъектФиктивная = Истина;
			
			КонецЕсли;
			
			Если СсылкаНаОбъект <> Неопределено 
				И СсылкаНаОбъект.Пустая() Тогда
						
				СсылкаНаОбъект = Неопределено;
						
			КонецЕсли;
			
			Если СсылкаНаОбъект <> Неопределено
				ИЛИ СозданныйОбъект <> Неопределено Тогда

				ДобавитьСсылкуВСписокЗагруженныхОбъектов(НППГлобальнойСсылки, НППСсылки, СсылкаНаОбъект, СсылкаНаОбъектФиктивная);
				
			КонецЕсли;
			
			Возврат СсылкаНаОбъект;	
			
		КонецЕсли;
		
	КонецЕсли;
		
	Если СсылкаНаОбъект <> Неопределено 
		И СсылкаНаОбъект.Пустая() Тогда
		
		СсылкаНаОбъект = Неопределено;
		
	КонецЕсли;
		
	// СсылкаНаОбъект пока не найден.
	Если СсылкаНаОбъект <> Неопределено
		ИЛИ СозданныйОбъект <> Неопределено Тогда
		
		ДобавитьСсылкуВСписокЗагруженныхОбъектов(НППГлобальнойСсылки, НППСсылки, СсылкаНаОбъект);
		Возврат СсылкаНаОбъект;
		
	КонецЕсли;
	
	НомерВариантаПоиска = 1;
	СтрокаИменСвойствПоиска = "";
	ПредыдущаяСтрокаПоиска = Неопределено;
	ПрекратитьПоиск = Ложь;
	УстанавливатьУОбъектаВсеСвойстваПоиска = Истина;
	
	Если Не ПустаяСтрока(ИмяПКО) Тогда
		
		ПКО = Правила[ИмяПКО];
		
	КонецЕсли;
	
	Если ПКО = Неопределено Тогда
		
		ПКО = ОпределитьПоТипуОбъектаПриемникаПравилоКонвертацииКотороеСодержитАлгоритмПоиска(СтруктураСвойств.ТипСсылкиСтрокой);
		
	КонецЕсли;
	
	Если ПКО <> Неопределено Тогда
		
		АлгоритмПоиска = ПКО.ПоследовательностьПолейПоиска;
		
	КонецЕсли;
	
	ЕстьАлгоритмПоиска = Не ПустаяСтрока(АлгоритмПоиска);
	
	Пока НомерВариантаПоиска <= 10
		И ЕстьАлгоритмПоиска Цикл
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКО, "ПоследовательностьПолейПоиска"));
					
			Иначе
				
				Выполнить(АлгоритмПоиска);
			
			КонецЕсли;
			
		Исключение
			
			ЗаписатьИнформациюОбОшибкеЗагрузкиОбработчикаПКО(73, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), "", "",
				ТипОбъекта, Неопределено, НСтр("ru = 'Последовательность полей поиска'"));
			
		КонецПопытки;
		
		НеНужноВыполнятьПоиск = ПрекратитьПоиск = Истина 
			ИЛИ СтрокаИменСвойствПоиска = ПредыдущаяСтрокаПоиска
			ИЛИ ЗначениеЗаполнено(СсылкаНаОбъект);
		
		Если НЕ НеНужноВыполнятьПоиск Тогда
		
			// сам поиск непосредственно
			СсылкаНаОбъект = НайтиЭлементПоСвойствамПоиска(ТипОбъекта, ИмяТипаОбъекта, СвойстваПоиска, СтруктураСвойств, 
				СтрокаИменСвойствПоиска, ПоискПоДатеНаРавенство);
				
			НеНужноВыполнятьПоиск = ЗначениеЗаполнено(СсылкаНаОбъект);
			
			Если СсылкаНаОбъект <> Неопределено
				И СсылкаНаОбъект.Пустая() Тогда
				СсылкаНаОбъект = Неопределено;
			КонецЕсли;
			
		КонецЕсли;
			
		Если НеНужноВыполнятьПоиск Тогда
			
			Если РежимПоискаОсновногоОбъекта И УстанавливатьУОбъектаВсеСвойстваПоиска = Истина Тогда
				
				ОбработатьУстановкуСвойствПоискаУОбъекта(УстанавливатьУОбъектаВсеСвойстваПоиска, ТипОбъекта, СвойстваПоиска, СвойстваПоискаНеЗамещать,
					СсылкаНаОбъект, СозданныйОбъект, НЕ РежимПоискаОсновногоОбъекта, СвойстваОбъектаМодифицированы);
				
			КонецЕсли;
			
			Прервать;
			
		КонецЕсли;
		
		НомерВариантаПоиска = НомерВариантаПоиска + 1;
		ПредыдущаяСтрокаПоиска = СтрокаИменСвойствПоиска;
		
	КонецЦикла;
	
	Если Не ЕстьАлгоритмПоиска Тогда
		
		// Сам поиск непосредственно и без алгоритма поиска.
		СсылкаНаОбъект = НайтиЭлементПоСвойствамПоиска(ТипОбъекта, ИмяТипаОбъекта, СвойстваПоиска, СтруктураСвойств, 
					СтрокаИменСвойствПоиска, ПоискПоДатеНаРавенство);
		
	КонецЕсли;
	
	ОбъектНайден = ЗначениеЗаполнено(СсылкаНаОбъект);
	
	Если РежимПоискаОсновногоОбъекта
		И ЗначениеЗаполнено(СсылкаНаОбъект)
		И (ИмяТипаОбъекта = "Документ" 
		ИЛИ ИмяТипаОбъекта = "Задача"
		ИЛИ ИмяТипаОбъекта = "БизнесПроцесс") Тогда
		
		// Если у документа дата есть в свойствах поиска - то устанавливаем ее.
		ДатаПустая = Не ЗначениеЗаполнено(СвойстваПоиска["Дата"]);
		МожноЗамещать = (Не ДатаПустая) 
			И (СвойстваПоискаНеЗамещать["Дата"] = Неопределено);
			
		Если МожноЗамещать Тогда
			
			Если СозданныйОбъект = Неопределено Тогда
				СозданныйОбъект = СсылкаНаОбъект.ПолучитьОбъект();
			КонецЕсли;
			
			СозданныйОбъект.Дата = СвойстваПоиска["Дата"];
			
		КонецЕсли;
		
	КонецЕсли;
	
	// Создавать новый объект нужно не всегда.
	Если Не ЗначениеЗаполнено(СсылкаНаОбъект)
		И СозданныйОбъект = Неопределено Тогда 
		
		Если ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD Тогда
			
			СсылкаНаОбъект = СтруктураСвойств.Менеджер.ПолучитьСсылку(Новый УникальныйИдентификатор(СвойствоУникальныйИдентификатор));	
			СсылкаНаОбъектФиктивная = Истина;
			
		ИначеЕсли НЕ НеСоздаватьОбъектЕслиНеНайден Тогда
		
			СсылкаНаОбъект = СоздатьНовыйОбъект(ТипОбъекта, СвойстваПоиска, СозданныйОбъект, НЕ РежимПоискаОсновногоОбъекта, , ИзвестнаяСсылкаУникальногоИдентификатора, НППСсылки, 
				НППГлобальнойСсылки, ,УстанавливатьУОбъектаВсеСвойстваПоиска);
				
			СвойстваОбъектаМодифицированы = Истина;
				
		КонецЕсли;
			
		ОбъектНайден = Ложь;
		
	Иначе
		
		ОбъектНайден = ЗначениеЗаполнено(СсылкаНаОбъект);
		
	КонецЕсли;
	
	Если СсылкаНаОбъект <> Неопределено
		И СсылкаНаОбъект.Пустая() Тогда
		
		СсылкаНаОбъект = Неопределено;
		
	КонецЕсли;
	
	ДобавитьСсылкуВСписокЗагруженныхОбъектов(НППГлобальнойСсылки, НППСсылки, СсылкаНаОбъект, СсылкаНаОбъектФиктивная);
		
	Возврат СсылкаНаОбъект;
	
КонецФункции

// Устанавливает свойства объекта (записи).
//
// Параметры:
//  Запись         - объект, свойства которого устанавливаем.
//                   Например, строка табличной части или запись регистра.
//
Процедура УстановитьСвойстваЗаписи(Объект, Запись, ИнформацияОТипах,
	ПараметрыОбъекта, ИмяВетки, ДанныеПоискаПоТЧ, КопияТЧДляПоиска, НомерЗаписи)
	
	НужноОрганизоватьПоискПоТЧ = (ДанныеПоискаПоТЧ <> Неопределено)
								И (КопияТЧДляПоиска <> Неопределено)
								И КопияТЧДляПоиска.Количество() <> 0;
								
	Если НужноОрганизоватьПоискПоТЧ Тогда
		
		СтруктураЧтенияСвойств = Новый Структура();
		СтруктураЧтенияСубконто = Новый Структура();
		
	КонецЕсли;
		
	Пока ФайлОбмена.Прочитать() Цикл
		
		ИмяУзла = ФайлОбмена.ЛокальноеИмя;
		
		Если ИмяУзла = "Свойство"
			ИЛИ ИмяУзла = "ЗначениеПараметра" Тогда
			
			ЭтоПараметр = (ИмяУзла = "ЗначениеПараметра");
			
			Имя    = одАтрибут(ФайлОбмена, одТипСтрока, "Имя");
			ИмяПКО = одАтрибут(ФайлОбмена, одТипСтрока, "ИмяПКО");
			
			Если Имя = "ВидДвижения" И СтрНайти(Метаданные.НайтиПоТипу(ТипЗнч(Запись)).ПолноеИмя(), "РегистрНакопления") Тогда
				
				ТипСвойства = одТипВидДвиженияНакопления;
				
			Иначе
				
				ТипСвойства = ПолучитьТипСвойстваПоДополнительнымДанным(ИнформацияОТипах, Имя);
				
			КонецЕсли;
			
			ЗначениеСвойства = ПрочитатьСвойство(ТипСвойства, ИмяПКО);
			
			Если ЭтоПараметр Тогда
				ДобавитьСложныйПараметрПриНеобходимости(ПараметрыОбъекта, ИмяВетки, НомерЗаписи, Имя, ЗначениеСвойства);			
			ИначеЕсли НужноОрганизоватьПоискПоТЧ Тогда 
				СтруктураЧтенияСвойств.Вставить(Имя, ЗначениеСвойства);	
			Иначе
				
				Попытка
					
					Запись[Имя] = ЗначениеСвойства;
					
				Исключение
					
					ЗП = ПолучитьСтруктуруЗаписиПротокола(26, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
					ЗП.ИмяПКО           = ИмяПКО;
					ЗП.Объект           = Объект;
					ЗП.ТипОбъекта       = ТипЗнч(Объект);
					ЗП.Свойство         = Строка(Запись) + "." + Имя;
					ЗП.Значение         = ЗначениеСвойства;
					ЗП.ТипЗначения      = ТипЗнч(ЗначениеСвойства);
					СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(26, ЗП, Истина);
					
					Если Не ФлагРежимОтладки Тогда
						ВызватьИсключение СтрокаСообщенияОбОшибке;
					КонецЕсли;
				КонецПопытки;
				
			КонецЕсли;
			
		ИначеЕсли ИмяУзла = "СубконтоДт" ИЛИ ИмяУзла = "СубконтоКт" Тогда
			
			// Поиск по субконто не реализован.
			
			Ключ = Неопределено;
			Значение = Неопределено;
			
			Пока ФайлОбмена.Прочитать() Цикл
				
				ИмяУзла = ФайлОбмена.ЛокальноеИмя;
								
				Если ИмяУзла = "Свойство" Тогда
					
					Имя    = одАтрибут(ФайлОбмена, одТипСтрока, "Имя");
					ИмяПКО = одАтрибут(ФайлОбмена, одТипСтрока, "ИмяПКО");
					ТипСвойства = ПолучитьТипСвойстваПоДополнительнымДанным(ИнформацияОТипах, Имя);
										
					Если Имя = "Ключ" Тогда
						
						Ключ = ПрочитатьСвойство(ТипСвойства);
						
					ИначеЕсли Имя = "Значение" Тогда
						
						Значение = ПрочитатьСвойство(ТипСвойства, ИмяПКО);
						
					КонецЕсли;
					
				ИначеЕсли (ИмяУзла = "СубконтоДт" ИЛИ ИмяУзла = "СубконтоКт") И (ФайлОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
					
					Прервать;
					
				Иначе
					
					ЗаписатьВПротоколВыполнения(9);
					Прервать;
					
				КонецЕсли;
				
			КонецЦикла;
			
			Если Ключ <> Неопределено 
				И Значение <> Неопределено Тогда
				
				Если НЕ НужноОрганизоватьПоискПоТЧ Тогда
				
					Запись[ИмяУзла][Ключ] = Значение;
					
				Иначе
					
					СоответствиеЗаписи = Неопределено;
					Если НЕ СтруктураЧтенияСубконто.Свойство(ИмяУзла, СоответствиеЗаписи) Тогда
						СоответствиеЗаписи = Новый Соответствие;
						СтруктураЧтенияСубконто.Вставить(ИмяУзла, СоответствиеЗаписи);
					КонецЕсли;
					
					СоответствиеЗаписи.Вставить(Ключ, Значение);
					
				КонецЕсли;
				
			КонецЕсли;
				
		ИначеЕсли (ИмяУзла = "Запись") И (ФайлОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			
			Прервать;
			
		Иначе
			
			ЗаписатьВПротоколВыполнения(9);
			Прервать;
			
		КонецЕсли;
		
	КонецЦикла;
	
	Если НужноОрганизоватьПоискПоТЧ Тогда
		
		СтруктураПоиска = Новый Структура();
		
		Для Каждого ЭлементПоиска Из  ДанныеПоискаПоТЧ.ПоляПоискаТЧ Цикл
			
			ЗначениеЭлемента = Неопределено;
			СтруктураЧтенияСвойств.Свойство(ЭлементПоиска, ЗначениеЭлемента);
			
			СтруктураПоиска.Вставить(ЭлементПоиска, ЗначениеЭлемента);		
			
		КонецЦикла;		
		
		МассивРезультатовПоиска = КопияТЧДляПоиска.НайтиСтроки(СтруктураПоиска);
		
		НайденаЗапись = МассивРезультатовПоиска.Количество() > 0;
		Если НайденаЗапись Тогда
			ЗаполнитьЗначенияСвойств(Запись, МассивРезультатовПоиска[0]);
		КонецЕсли;
		
		// Поверх заполнение свойствами и значением субконто.
		Для Каждого КлючИЗначение Из СтруктураЧтенияСвойств Цикл
			
			Запись[КлючИЗначение.Ключ] = КлючИЗначение.Значение;
			
		КонецЦикла;
		
		Для Каждого ЭлементИмя Из СтруктураЧтенияСубконто Цикл
			
			Для Каждого ЭлементКлюч Из ЭлементИмя.Значение Цикл
			
				Запись[ЭлементИмя.Ключ][ЭлементКлюч.Ключ] = ЭлементКлюч.Значение;
				
			КонецЦикла;
			
		КонецЦикла;
		
	КонецЕсли;
	
КонецПроцедуры

// Загружает табличную часть объекта.
//
// Параметры:
//  Объект         - объект, табличную часть которого загружаем.
//  Имя            - имя табличной части.
//  Очистить       - если Истина, то табличная часть предварительно очищается.
// 
Процедура ЗагрузитьТабличнуюЧасть(Объект, Имя, Очистить, ОбщаяИнформацияОТипеДокумента, НужноЗаписатьОбъект, 
	ПараметрыОбъекта, Правило)

	ИмяТабличнойЧасти = Имя + "ТабличнаяЧасть";
	Если ОбщаяИнформацияОТипеДокумента <> Неопределено Тогда
		ИнформацияОТипах = ОбщаяИнформацияОТипеДокумента[ИмяТабличнойЧасти];
	Иначе
	    ИнформацияОТипах = Неопределено;
	КонецЕсли;
			
	ДанныеПоискаПоТЧ = Неопределено;
	Если Правило <> Неопределено Тогда
		ДанныеПоискаПоТЧ = Правило.ПоискПоТабличнымЧастям.Найти("ТабличнаяЧасть." + Имя, "ИмяЭлемента");
	КонецЕсли;
	
	КопияТЧДляПоиска = Неопределено;
	
	ТЧ = Объект[Имя];

	Если Очистить
		И ТЧ.Количество() <> 0 Тогда
		
		НужноЗаписатьОбъект = Истина;
		
		Если ДанныеПоискаПоТЧ <> Неопределено Тогда
			КопияТЧДляПоиска = ТЧ.Выгрузить();
		КонецЕсли;
		ТЧ.Очистить();
		
	ИначеЕсли ДанныеПоискаПоТЧ <> Неопределено Тогда
		
		КопияТЧДляПоиска = ТЧ.Выгрузить();
		
	КонецЕсли;
	
	НомерЗаписи = 0;
	Пока ФайлОбмена.Прочитать() Цикл
		
		ИмяУзла = ФайлОбмена.ЛокальноеИмя;
		
		Если ИмяУзла = "Запись" Тогда
			Попытка
				
				НужноЗаписатьОбъект = Истина;
				Запись = ТЧ.Добавить();
				
			Исключение
				Запись = Неопределено;
			КонецПопытки;
			
			Если Запись = Неопределено Тогда
				одПропустить(ФайлОбмена);
			Иначе
				УстановитьСвойстваЗаписи(Объект, Запись, ИнформацияОТипах, ПараметрыОбъекта, ИмяТабличнойЧасти, ДанныеПоискаПоТЧ, КопияТЧДляПоиска, НомерЗаписи);
			КонецЕсли;
			
			НомерЗаписи = НомерЗаписи + 1;
			
		ИначеЕсли (ИмяУзла = "ТабличнаяЧасть") И (ФайлОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			
			Прервать;
			
		Иначе
			
			ЗаписатьВПротоколВыполнения(9);
			Прервать;
			
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры 

// Загружает движения объекта
//
// Параметры:
//  Объект         - объект, движения которого загружаем.
//  Имя            - имя регистра.
//  Очистить       - если Истина, то движения предварительно очищается.
// 
Процедура ЗагрузитьДвижения(Объект, Имя, Очистить, ОбщаяИнформацияОТипеДокумента, НужноЗаписатьОбъект, 
	ПараметрыОбъекта, Правило)
	
	ИмяДвижений = Имя + "НаборЗаписей";
	Если ОбщаяИнформацияОТипеДокумента <> Неопределено Тогда
		ИнформацияОТипах = ОбщаяИнформацияОТипеДокумента[ИмяДвижений];
	Иначе
	    ИнформацияОТипах = Неопределено;
	КонецЕсли;
	
	ДанныеПоискаПоТЧ = Неопределено;
	Если Правило <> Неопределено Тогда
		ДанныеПоискаПоТЧ = Правило.ПоискПоТабличнымЧастям.Найти("НаборЗаписей." + Имя, "ИмяЭлемента");
	КонецЕсли;
	
	КопияТЧДляПоиска = Неопределено;
	
	Движения = Объект.Движения[Имя];
	Движения.Записывать = Истина;
	
	Если Движения.Количество()=0 Тогда
		Движения.Прочитать();
	КонецЕсли;
	
	Если Очистить
		И Движения.Количество() <> 0 Тогда
		
		НужноЗаписатьОбъект = Истина;
		
		Если ДанныеПоискаПоТЧ <> Неопределено Тогда 
			КопияТЧДляПоиска = Движения.Выгрузить();
		КонецЕсли;
		
        Движения.Очистить();
		
	ИначеЕсли ДанныеПоискаПоТЧ <> Неопределено Тогда
		
		КопияТЧДляПоиска = Движения.Выгрузить();	
		
	КонецЕсли;
	
	НомерЗаписи = 0;
	Пока ФайлОбмена.Прочитать() Цикл
		
		ИмяУзла = ФайлОбмена.ЛокальноеИмя;
			
		Если ИмяУзла = "Запись" Тогда
			
			Запись = Движения.Добавить();
			НужноЗаписатьОбъект = Истина;
			УстановитьСвойстваЗаписи(Объект, Запись, ИнформацияОТипах, ПараметрыОбъекта, ИмяДвижений, ДанныеПоискаПоТЧ, КопияТЧДляПоиска, НомерЗаписи);
			НомерЗаписи = НомерЗаписи + 1;
			
		ИначеЕсли (ИмяУзла = "НаборЗаписей") И (ФайлОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			
			Прервать;
			
		Иначе
			
			ЗаписатьВПротоколВыполнения(9);
			Прервать;
			
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

// Загружает объект типа ОписаниеТипов из указанного xml-источника.
//
// Параметры:
//  Источник - ЗаписьXML - xml-источник.
// 
Функция ЗагрузитьТипыОбъекта(Источник)
	
	// КвалификаторыДаты
	
	СоставДаты =  одАтрибут(Источник, одТипСтрока,  "СоставДаты");
	
	// КвалификаторыСтроки
	
	Длина           =  одАтрибут(Источник, одТипЧисло,  "Длина");
	ДлинаДопустимая =  одАтрибут(Источник, одТипСтрока, "ДопустимаяДлина");
	
	// КвалификаторыЧисла
	
	Разрядность             = одАтрибут(Источник, одТипЧисло,  "Разрядность");
	РазрядностьДробнойЧасти = одАтрибут(Источник, одТипЧисло,  "РазрядностьДробнойЧасти");
	ЗнакДопустимый          = одАтрибут(Источник, одТипСтрока, "ДопустимыйЗнак");
	
	// Читаем массив типов
	
	МассивТипов = Новый Массив;
	
	Пока Источник.Прочитать() Цикл
		ИмяУзла = Источник.ЛокальноеИмя;
		
		Если      ИмяУзла = "Тип" Тогда
			МассивТипов.Добавить(Тип(одЗначениеЭлемента(Источник, одТипСтрока)));
		ИначеЕсли (ИмяУзла = "Типы") И ( Источник.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			Прервать;
		Иначе
			ЗаписатьВПротоколВыполнения(9);
			Прервать;
		КонецЕсли;
		
	КонецЦикла;
	
	Если МассивТипов.Количество() > 0 Тогда
		
		// КвалификаторыДаты
		
		Если СоставДаты = "Дата" Тогда
			КвалификаторыДаты   = Новый КвалификаторыДаты(ЧастиДаты.Дата);
		ИначеЕсли СоставДаты = "ДатаВремя" Тогда
			КвалификаторыДаты   = Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя);
		ИначеЕсли СоставДаты = "Время" Тогда
			КвалификаторыДаты   = Новый КвалификаторыДаты(ЧастиДаты.Время);
		Иначе
			КвалификаторыДаты   = Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя);
		КонецЕсли;
		
		// КвалификаторыЧисла
		
		Если Разрядность > 0 Тогда
			Если ЗнакДопустимый = "Неотрицательный" Тогда
				Знак = ДопустимыйЗнак.Неотрицательный;
			Иначе
				Знак = ДопустимыйЗнак.Любой;
			КонецЕсли; 
			КвалификаторыЧисла  = Новый КвалификаторыЧисла(Разрядность, РазрядностьДробнойЧасти, Знак);
		Иначе
			КвалификаторыЧисла  = Новый КвалификаторыЧисла();
		КонецЕсли;
		
		// КвалификаторыСтроки
		
		Если Длина > 0 Тогда
			Если ДлинаДопустимая = "Фиксированная" Тогда
				ДлинаДопустимая = ДопустимаяДлина.Фиксированная;
			Иначе
				ДлинаДопустимая = ДопустимаяДлина.Переменная;
			КонецЕсли;
			КвалификаторыСтроки = Новый КвалификаторыСтроки(Длина, ДлинаДопустимая);
		Иначе
			КвалификаторыСтроки = Новый КвалификаторыСтроки();
		КонецЕсли;
		
		Возврат Новый ОписаниеТипов(МассивТипов, КвалификаторыЧисла, КвалификаторыСтроки, КвалификаторыДаты);
	КонецЕсли;
	
	Возврат Неопределено;
	
КонецФункции

Процедура УстановитьПометкуУдаленияУОбъекта(Объект, ПометкаУдаления, ИмяТипаОбъекта)
	
	Если (ПометкаУдаления = Неопределено)
		И (Объект.ПометкаУдаления <> Истина) Тогда
		
		Возврат;
		
	КонецЕсли;
	
	ПометкаДляУстановки = ?(ПометкаУдаления <> Неопределено, ПометкаУдаления, Ложь);
	
	УстановитьОбменДаннымиЗагрузка(Объект);
		
	// Дли иерархических объектов пометку удаления только у конкретного объекта ставим.
	Если ИмяТипаОбъекта = "Справочник"
		ИЛИ ИмяТипаОбъекта = "ПланВидовХарактеристик"
		ИЛИ ИмяТипаОбъекта = "ПланСчетов" Тогда
			
		Объект.УстановитьПометкуУдаления(ПометкаДляУстановки, Ложь);
			
	Иначе	
		
		Объект.УстановитьПометкуУдаления(ПометкаДляУстановки);
		
	КонецЕсли;
	
КонецПроцедуры

Процедура ЗаписатьДокументВБезопасномРежиме(Документ, ТипОбъекта)
	
	Если Документ.Проведен Тогда
						
		Документ.Проведен = Ложь;
			
	КонецЕсли;		
								
	ЗаписатьОбъектВИБ(Документ, ТипОбъекта);
	
КонецПроцедуры

Функция ПолучитьОбъектПоСсылкеИДопИнформации(СозданныйОбъект, Ссылка)
	
	// Если объект создали, то работаем с ним, если нашли - получаем объект.
	Если СозданныйОбъект <> Неопределено Тогда
		Объект = СозданныйОбъект;
	Иначе
		Если Ссылка.Пустая() Тогда
			Объект = Неопределено;
		Иначе
			Объект = Ссылка.ПолучитьОбъект();
		КонецЕсли;		
	КонецЕсли;
	
	Возврат Объект;
	
КонецФункции

Процедура КомментарииКЗагрузкеОбъекта(НПП, ИмяПравила, Источник, ТипОбъекта, ГНПП = 0)
	
	Если ФлагКомментироватьОбработкуОбъектов Тогда
		
		Если НПП <> 0 Тогда
			СтрокаСообщения = ПодставитьПараметрыВСтроку(НСтр("ru = 'Загрузка объекта № %1'"), НПП);
		Иначе
			СтрокаСообщения = ПодставитьПараметрыВСтроку(НСтр("ru = 'Загрузка объекта № %1'"), ГНПП);
		КонецЕсли;
		
		ЗП = ПолучитьСтруктуруЗаписиПротокола();
		
		Если Не ПустаяСтрока(ИмяПравила) Тогда
			
			ЗП.ИмяПКО = ИмяПравила;
			
		КонецЕсли;
		
		Если Не ПустаяСтрока(Источник) Тогда
			
			ЗП.Источник = Источник;
			
		КонецЕсли;
		
		ЗП.ТипОбъекта = ТипОбъекта;
		ЗаписатьВПротоколВыполнения(СтрокаСообщения, ЗП, Ложь);
		
	КонецЕсли;	
	
КонецПроцедуры

Процедура ДобавитьПараметрПриНеобходимости(ПараметрыДанных, ИмяПараметра, ЗначениеПараметра)
	
	Если ПараметрыДанных = Неопределено Тогда
		ПараметрыДанных = Новый Соответствие;
	КонецЕсли;
	
	ПараметрыДанных.Вставить(ИмяПараметра, ЗначениеПараметра);
	
КонецПроцедуры

Процедура ДобавитьСложныйПараметрПриНеобходимости(ПараметрыДанных, ИмяВеткиПараметров, НомерСтроки, ИмяПараметра, ЗначениеПараметра)
	
	Если ПараметрыДанных = Неопределено Тогда
		ПараметрыДанных = Новый Соответствие;
	КонецЕсли;
	
	ТекущиеДанныеПараметра = ПараметрыДанных[ИмяВеткиПараметров];
	
	Если ТекущиеДанныеПараметра = Неопределено Тогда
		
		ТекущиеДанныеПараметра = Новый ТаблицаЗначений;
		ТекущиеДанныеПараметра.Колонки.Добавить("НомерСтроки");
		ТекущиеДанныеПараметра.Колонки.Добавить("ИмяПараметра");
		ТекущиеДанныеПараметра.Индексы.Добавить("НомерСтроки");
		
		ПараметрыДанных.Вставить(ИмяВеткиПараметров, ТекущиеДанныеПараметра);	
		
	КонецЕсли;
	
	Если ТекущиеДанныеПараметра.Колонки.Найти(ИмяПараметра) = Неопределено Тогда
		ТекущиеДанныеПараметра.Колонки.Добавить(ИмяПараметра);
	КонецЕсли;		
	
	ДанныеСтроки = ТекущиеДанныеПараметра.Найти(НомерСтроки, "НомерСтроки");
	Если ДанныеСтроки = Неопределено Тогда
		ДанныеСтроки = ТекущиеДанныеПараметра.Добавить();
		ДанныеСтроки.НомерСтроки = НомерСтроки;
	КонецЕсли;		
	
	ДанныеСтроки[ИмяПараметра] = ЗначениеПараметра;
	
КонецПроцедуры

Процедура УстановитьСсылкуДляОбъекта(СтрокаСтекаНезаписанныхОбъектов)
	
	// Объект еще не записан, а на него ссылаются.
	ОбъектДляЗаписи = СтрокаСтекаНезаписанныхОбъектов.Объект;
	
	СвойстваМД      = Менеджеры[СтрокаСтекаНезаписанныхОбъектов.ТипОбъекта];
	Менеджер        = СвойстваМД.Менеджер;
		
	НовыйУникальныйИдентификатор = Новый УникальныйИдентификатор;
	НоваяСсылка = Менеджер.ПолучитьСсылку(НовыйУникальныйИдентификатор);
		
	ОбъектДляЗаписи.УстановитьСсылкуНового(НоваяСсылка);
	СтрокаСтекаНезаписанныхОбъектов.ИзвестнаяСсылка = НоваяСсылка;
	
КонецПроцедуры

Процедура ДополнитьСтекНеЗаписанныхОбъектов(НПП, ГНПП, Объект, ИзвестнаяСсылка, ТипОбъекта, ПараметрыОбъекта)
	
	НомерДляСтека = ?(НПП = 0, ГНПП, НПП);
	
	СтрокаСтека = мГлобальныйСтекНеЗаписанныхОбъектов[НомерДляСтека];
	Если СтрокаСтека <> Неопределено Тогда
		Возврат;
	КонецЕсли;
	СтруктураПараметров = Новый Структура();
	СтруктураПараметров.Вставить("Объект", Объект);
	СтруктураПараметров.Вставить("ИзвестнаяСсылка", ИзвестнаяСсылка);
	СтруктураПараметров.Вставить("ТипОбъекта", ТипОбъекта);
	СтруктураПараметров.Вставить("ПараметрыОбъекта", ПараметрыОбъекта);

	мГлобальныйСтекНеЗаписанныхОбъектов.Вставить(НомерДляСтека, СтруктураПараметров);
	
КонецПроцедуры

Процедура УдалитьИзСтекаНеЗаписанныхОбъектов(НПП, ГНПП)
	
	НомерДляСтека = ?(НПП = 0, ГНПП, НПП);
	СтрокаСтека = мГлобальныйСтекНеЗаписанныхОбъектов[НомерДляСтека];
	Если СтрокаСтека = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	мГлобальныйСтекНеЗаписанныхОбъектов.Удалить(НомерДляСтека);
	
КонецПроцедуры

Процедура ПровестиЗаписьНеЗаписанныхОбъектов()
	
	Если мГлобальныйСтекНеЗаписанныхОбъектов = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Для Каждого СтрокаДанных Из мГлобальныйСтекНеЗаписанныхОбъектов Цикл
		
		// отложенная запись объектов
		Объект = СтрокаДанных.Значение.Объект; // СправочникОбъект, ДокументОбъект, и т.п.
		НППСсылки = СтрокаДанных.Ключ;
		
		ЗаписатьОбъектВИБ(Объект, СтрокаДанных.Значение.ТипОбъекта);
		
		ДобавитьСсылкуВСписокЗагруженныхОбъектов(0, НППСсылки, Объект.Ссылка);
		
	КонецЦикла;
	
	мГлобальныйСтекНеЗаписанныхОбъектов.Очистить();
	
КонецПроцедуры

Процедура ПровестиГенерациюКодаНомераПриНеобходимости(ГенерироватьНовыйНомерИлиКодЕслиНеУказан, Объект, ИмяТипаОбъекта, НужноЗаписатьОбъект, 
	РежимОбменДанными)
	
	Если Не ГенерироватьНовыйНомерИлиКодЕслиНеУказан
		ИЛИ НЕ РежимОбменДанными Тогда
		
		// Если номер не нужно генерировать, или не в режиме обмена данными то ничего не нужно делать... платформа сама все
		// сгенерирует.
		Возврат;
	КонецЕсли;
	
	// По типу документа смотрим заполнен кол или номер.
	Если ИмяТипаОбъекта = "Документ"
		ИЛИ ИмяТипаОбъекта =  "БизнесПроцесс"
		ИЛИ ИмяТипаОбъекта = "Задача" Тогда
		
		Если НЕ ЗначениеЗаполнено(Объект.Номер) Тогда
			
			Объект.УстановитьНовыйНомер();
			НужноЗаписатьОбъект = Истина;
			
		КонецЕсли;
		
	ИначеЕсли ИмяТипаОбъекта = "Справочник"
		ИЛИ ИмяТипаОбъекта = "ПланВидовХарактеристик"
		ИЛИ ИмяТипаОбъекта = "ПланОбмена" Тогда
		
		Если НЕ ЗначениеЗаполнено(Объект.Код) Тогда
			
			Объект.УстановитьНовыйКод();
			НужноЗаписатьОбъект = Истина;
			
		КонецЕсли;	
		
	КонецЕсли;
	
КонецПроцедуры

// Читает очередной объект из файла обмена, производит загрузку.
//
// Параметры:
//  Нет.
// 
Функция ПрочитатьОбъект()

	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	НПП						= одАтрибут(ФайлОбмена, одТипЧисло,  "Нпп");
	ГНПП					= одАтрибут(ФайлОбмена, одТипЧисло,  "ГНпп");
	Источник				= одАтрибут(ФайлОбмена, одТипСтрока, "Источник");
	ИмяПравила				= одАтрибут(ФайлОбмена, одТипСтрока, "ИмяПравила");
	НеЗамещатьОбъект 		= одАтрибут(ФайлОбмена, одТипБулево, "НеЗамещать");
	ПрефиксАвтонумерации	= одАтрибут(ФайлОбмена, одТипСтрока, "ПрефиксАвтонумерации");
	ТипОбъектаСтрокой       = одАтрибут(ФайлОбмена, одТипСтрока, "Тип");
	ТипОбъекта 				= Тип(ТипОбъектаСтрокой);
	ИнформацияОТипах = мСоответствиеТиповДанныхДляЗагрузки[ТипОбъекта];

	КомментарииКЗагрузкеОбъекта(НПП, ИмяПравила, Источник, ТипОбъекта, ГНПП);    
	
	СтруктураСвойств = Менеджеры[ТипОбъекта];
	ИмяТипаОбъекта   = СтруктураСвойств.ИмяТипа;

	Если ИмяТипаОбъекта = "Документ" Тогда
		
		РежимЗаписи     = одАтрибут(ФайлОбмена, одТипСтрока, "РежимЗаписи");
		РежимПроведения = одАтрибут(ФайлОбмена, одТипСтрока, "РежимПроведения");
		
	КонецЕсли;	
	
	Ссылка          = Неопределено;
	Объект          = Неопределено; // СправочникОбъект, ДокументОбъект, РегистрСведенийНаборЗаписей, и т.п.
	ОбъектНайден    = Истина;
	ПометкаУдаления = Неопределено;
	
	СвойстваПоиска  = Новый Соответствие;
	СвойстваПоискаНеЗамещать  = Новый Соответствие;
	
	НужноЗаписатьОбъект = НЕ ЗаписыватьВИнформационнуюБазуТолькоИзмененныеОбъекты;
	


	Если Не ПустаяСтрока(ИмяПравила) Тогда
		
		Правило = Правила[ИмяПравила];
		ЕстьОбработчикПередЗагрузкой = Правило.ЕстьОбработчикПередЗагрузкой;
		ЕстьОбработчикПриЗагрузке    = Правило.ЕстьОбработчикПриЗагрузке;
		ЕстьОбработчикПослеЗагрузки  = Правило.ЕстьОбработчикПослеЗагрузки;
		ГенерироватьНовыйНомерИлиКодЕслиНеУказан = Правило.ГенерироватьНовыйНомерИлиКодЕслиНеУказан;
		
	Иначе
		
		ЕстьОбработчикПередЗагрузкой = Ложь;
		ЕстьОбработчикПриЗагрузке    = Ложь;
		ЕстьОбработчикПослеЗагрузки  = Ложь;
		ГенерироватьНовыйНомерИлиКодЕслиНеУказан = Ложь;
		
	КонецЕсли;


    // Глобальный обработчик события ПередЗагрузкойОбъекта.
	Если ЕстьГлобальныйОбработчикПередЗагрузкойОбъекта Тогда
		
		Отказ = Ложь;
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(Конвертация, "ПередЗагрузкойОбъекта"));
				
			Иначе
				
				Выполнить(Конвертация.ПередЗагрузкойОбъекта);
				
			КонецЕсли;
			
		Исключение
			
			ИмяОбработчика = НСтр("ru = '%1 (глобальный)'");
			ЗаписатьИнформациюОбОшибкеЗагрузкиОбработчикаПКО(53, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), 
				ИмяПравила, Источник, ТипОбъекта, Неопределено,
				ПодставитьПараметрыВСтроку(ИмяОбработчика, "ПередЗагрузкойОбъекта"));
							
		КонецПопытки;
						
		Если Отказ Тогда	//	Отказ от загрузки объекта
			
			одПропустить(ФайлОбмена, "Объект");
			Возврат Неопределено;
			
		КонецЕсли;
		
	КонецЕсли;
	
	
	// Обработчик события ПередЗагрузкойОбъекта.
	Если ЕстьОбработчикПередЗагрузкой Тогда
		
		Отказ = Ложь;
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(Правило, "ПередЗагрузкой"));
				
			Иначе
				
				Выполнить(Правило.ПередЗагрузкой);
				
			КонецЕсли;
			
		Исключение
			
			ЗаписатьИнформациюОбОшибкеЗагрузкиОбработчикаПКО(19, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				ИмяПравила, Источник, ТипОбъекта, Неопределено, "ПередЗагрузкойОбъекта");
			
		КонецПопытки;
		
		Если Отказ Тогда // Отказ от загрузки объекта
			
			одПропустить(ФайлОбмена, "Объект");
			Возврат Неопределено;
			
		КонецЕсли;
		
	КонецЕсли;
	
	СвойстваОбъектаМодифицированы = Ложь;
	НаборЗаписей = Неопределено;
	НППГлобальнойСсылки = 0;
	НППСсылки = 0;
	ПараметрыОбъекта = Неопределено;
		
	Пока ФайлОбмена.Прочитать() Цикл
		
		ИмяУзла = ФайлОбмена.ЛокальноеИмя;
				
		Если ИмяУзла = "Свойство"
			ИЛИ ИмяУзла = "ЗначениеПараметра" Тогда
			
			ЭтоПараметрДляОбъекта = (ИмяУзла = "ЗначениеПараметра");
			
			Если НЕ ЭтоПараметрДляОбъекта
				И Объект = Неопределено Тогда
				
				// Объект не нашли и не создали - попробуем сейчас это сделать.
				ОбъектНайден = Ложь;

			    // Обработчик события ПриЗагрузкеОбъекта.
				Если ЕстьОбработчикПриЗагрузке Тогда
					
					// Если есть обработчик при загрузке, то объект нужно перезаписывать, так как могут быть изменения.
					НужноБылоЗаписатьОбъект = НужноЗаписатьОбъект;
					ОбъектМодифицирован = Истина;
										
					Попытка
						
						Если ФлагРежимОтладкиОбработчиков Тогда
							
							Выполнить(ПолучитьСтрокуВызоваОбработчика(Правило, "ПриЗагрузке"));
							
						Иначе
							
							Выполнить(Правило.ПриЗагрузке);
						
						КонецЕсли;
						НужноЗаписатьОбъект = ОбъектМодифицирован ИЛИ НужноБылоЗаписатьОбъект;
						
					Исключение
						
						ЗаписатьИнформациюОбОшибкеЗагрузкиОбработчикаПКО(20, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
							ИмяПравила, Источник, ТипОбъекта, Объект, "ПриЗагрузкеОбъекта");
						
					КонецПопытки;
					
				КонецЕсли;

				// Так м не смогли создать объект в событии - создаем его отдельно.
				Если Объект = Неопределено Тогда
					
					НужноЗаписатьОбъект = Истина;
					
					Если ИмяТипаОбъекта = "Константы" Тогда
						
						Объект = Константы.СоздатьНабор();
						Объект.Прочитать();
						
					Иначе
						
						СоздатьНовыйОбъект(ТипОбъекта, СвойстваПоиска, Объект, Ложь, НаборЗаписей, , НППСсылки, НППГлобальнойСсылки, ПараметрыОбъекта);
												
					КонецЕсли;
					
				КонецЕсли;
				
			КонецЕсли;
			
			Имя                = одАтрибут(ФайлОбмена, одТипСтрока, "Имя");
			НеЗамещатьСвойство = одАтрибут(ФайлОбмена, одТипБулево, "НеЗамещать");
			ИмяПКО             = одАтрибут(ФайлОбмена, одТипСтрока, "ИмяПКО");
			
			Если НЕ ЭтоПараметрДляОбъекта
				И ((ОбъектНайден И НеЗамещатьСвойство) 
				ИЛИ (Имя = "ЭтоГруппа")
				ИЛИ (Объект[Имя] = NULL)) Тогда
				
				// неизвестное свойство
				одПропустить(ФайлОбмена, ИмяУзла);
				Продолжить;
				
			КонецЕсли; 

			
			// Читаем и устанавливаем значение свойства.
			ТипСвойства = ПолучитьТипСвойстваПоДополнительнымДанным(ИнформацияОТипах, Имя);
			Значение    = ПрочитатьСвойство(ТипСвойства, ИмяПКО);
			
			Если ЭтоПараметрДляОбъекта Тогда
				
				// Дополняем коллекцию параметров объекта.
				ДобавитьПараметрПриНеобходимости(ПараметрыОбъекта, Имя, Значение);
				
			Иначе
			
				Если Имя = "ПометкаУдаления" Тогда
					
					ПометкаУдаления = Значение;
					
					Если Объект.ПометкаУдаления <> ПометкаУдаления Тогда
						Объект.ПометкаУдаления = ПометкаУдаления;
						НужноЗаписатьОбъект = Истина;
					КонецЕсли;
										
				Иначе
					
					Попытка
						
						Если Не НужноЗаписатьОбъект Тогда
							
							НужноЗаписатьОбъект = (Объект[Имя] <> Значение);
							
						КонецЕсли;
						
						Объект[Имя] = Значение;
						
					Исключение
						
						ЗП = ПолучитьСтруктуруЗаписиПротокола(26, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
						ЗП.ИмяПКО           = ИмяПравила;
						ЗП.НПП              = НПП;
						ЗП.ГНПП             = ГНПП;
						ЗП.Источник         = Источник;
						ЗП.Объект           = Объект;
						ЗП.ТипОбъекта       = ТипОбъекта;
						ЗП.Свойство         = Имя;
						ЗП.Значение         = Значение;
						ЗП.ТипЗначения      = ТипЗнч(Значение);
						СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(26, ЗП, Истина);
						
						Если Не ФлагРежимОтладки Тогда
							ВызватьИсключение СтрокаСообщенияОбОшибке;
						КонецЕсли;
						
					КонецПопытки;					
									
				КонецЕсли;
				
			КонецЕсли;
			
		ИначеЕсли ИмяУзла = "Ссылка" Тогда
			
			// Ссылка на элемент - сначала получаем по ссылке объект, а потом устанавливаем свойства.
			СозданныйОбъект = Неопределено;
			НеСоздаватьОбъектЕслиНеНайден = Неопределено;
			ИзвестнаяСсылкаУникальногоИдентификатора = Неопределено;
			
			Ссылка = НайтиОбъектПоСсылке(ТипОбъекта,
								ИмяПравила, 
								СвойстваПоиска,
								СвойстваПоискаНеЗамещать,
								ОбъектНайден,
								СозданныйОбъект,
								НеСоздаватьОбъектЕслиНеНайден,
								Истина,
								СвойстваОбъектаМодифицированы,
								НППГлобальнойСсылки,
								НППСсылки,
								ИзвестнаяСсылкаУникальногоИдентификатора,
								ПараметрыОбъекта);
			
			НужноЗаписатьОбъект = НужноЗаписатьОбъект ИЛИ СвойстваОбъектаМодифицированы;
			
			Если Ссылка = Неопределено
				И НеСоздаватьОбъектЕслиНеНайден = Истина Тогда
				
				одПропустить(ФайлОбмена, "Объект");
				Прервать;
			
			ИначеЕсли ИмяТипаОбъекта = "Перечисление" Тогда
				
				Объект = Ссылка;
			
			Иначе
				
				Объект = ПолучитьОбъектПоСсылкеИДопИнформации(СозданныйОбъект, Ссылка);
				
				Если ОбъектНайден И НеЗамещатьОбъект И (Не ЕстьОбработчикПриЗагрузке) Тогда
					
					одПропустить(ФайлОбмена, "Объект");
					Прервать;
					
				КонецЕсли;
				
				Если Ссылка = Неопределено Тогда
					
					ДополнитьСтекНеЗаписанныхОбъектов(НПП, ГНПП, СозданныйОбъект, ИзвестнаяСсылкаУникальногоИдентификатора, ТипОбъекта, ПараметрыОбъекта);
					
				КонецЕсли;
							
			КонецЕсли; 
			
		    // Обработчик события ПриЗагрузкеОбъекта.
			Если ЕстьОбработчикПриЗагрузке Тогда
				
				НужноБылоЗаписатьОбъект = НужноЗаписатьОбъект;
				ОбъектМодифицирован = Истина;
				
				Попытка
					
					Если ФлагРежимОтладкиОбработчиков Тогда
						
						Выполнить(ПолучитьСтрокуВызоваОбработчика(Правило, "ПриЗагрузке"));
						
					Иначе
						
						Выполнить(Правило.ПриЗагрузке);
						
					КонецЕсли;
					
					НужноЗаписатьОбъект = ОбъектМодифицирован ИЛИ НужноБылоЗаписатьОбъект;
					
				Исключение
					УдалитьИзСтекаНеЗаписанныхОбъектов(НПП, ГНПП);
					ЗаписатьИнформациюОбОшибкеЗагрузкиОбработчикаПКО(20, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
						ИмяПравила, Источник, ТипОбъекта, Объект, "ПриЗагрузкеОбъекта");
					
				КонецПопытки;
				
				Если ОбъектНайден И НеЗамещатьОбъект Тогда
					
					одПропустить(ФайлОбмена, "Объект");
					Прервать;
					
				КонецЕсли;
				
			КонецЕсли;
			
		ИначеЕсли ИмяУзла = "ТабличнаяЧасть"
			ИЛИ ИмяУзла = "НаборЗаписей" Тогда

			Если Объект = Неопределено Тогда
				
				ОбъектНайден = Ложь;

				// Обработчик события ПриЗагрузкеОбъекта.
				
				Если ЕстьОбработчикПриЗагрузке Тогда
					
					НужноБылоЗаписатьОбъект = НужноЗаписатьОбъект;
					ОбъектМодифицирован = Истина;
					
					Попытка
						
						Если ФлагРежимОтладкиОбработчиков Тогда
							
							Выполнить(ПолучитьСтрокуВызоваОбработчика(Правило, "ПриЗагрузке"));
							
						Иначе
							
							Выполнить(Правило.ПриЗагрузке);
							
						КонецЕсли;
						
						НужноЗаписатьОбъект = ОбъектМодифицирован ИЛИ НужноБылоЗаписатьОбъект;
						
					Исключение
						УдалитьИзСтекаНеЗаписанныхОбъектов(НПП, ГНПП);
						ЗаписатьИнформациюОбОшибкеЗагрузкиОбработчикаПКО(20, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
							ИмяПравила, Источник, ТипОбъекта, Объект, "ПриЗагрузкеОбъекта");
						
					КонецПопытки;
					
				КонецЕсли;
				
			КонецЕсли;
			
			Имя                = одАтрибут(ФайлОбмена, одТипСтрока, "Имя");
			НеЗамещатьСвойство = одАтрибут(ФайлОбмена, одТипБулево, "НеЗамещать");
			НеОчищать          = одАтрибут(ФайлОбмена, одТипБулево, "НеОчищать");

			Если ОбъектНайден И НеЗамещатьСвойство Тогда
				
				одПропустить(ФайлОбмена, ИмяУзла);
				Продолжить;
				
			КонецЕсли;
			
			Если Объект = Неопределено Тогда
					
				СоздатьНовыйОбъект(ТипОбъекта, СвойстваПоиска, Объект, Ложь, НаборЗаписей, , НППСсылки, НППГлобальнойСсылки, ПараметрыОбъекта);
				НужноЗаписатьОбъект = Истина;
									
			КонецЕсли;
			
			Если ИмяУзла = "ТабличнаяЧасть" Тогда
				
				// Загрузка элементов из табличной части.
				ЗагрузитьТабличнуюЧасть(Объект, Имя, Не НеОчищать, ИнформацияОТипах, НужноЗаписатьОбъект, ПараметрыОбъекта, Правило);
				
			ИначеЕсли ИмяУзла = "НаборЗаписей" Тогда
				
				// загрузка движений
				ЗагрузитьДвижения(Объект, Имя, Не НеОчищать, ИнформацияОТипах, НужноЗаписатьОбъект, ПараметрыОбъекта, Правило);
				
			КонецЕсли;			
			
		ИначеЕсли (ИмяУзла = "Объект") И (ФайлОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			
			Отказ = Ложь;
			
		    // Глобальный обработчик события ПослеЗагрузкиОбъекта.
			Если ЕстьГлобальныйОбработчикПослеЗагрузкиОбъекта Тогда
				
				НужноБылоЗаписатьОбъект = НужноЗаписатьОбъект;
				ОбъектМодифицирован = Истина;
				
				Попытка
					
					Если ФлагРежимОтладкиОбработчиков Тогда
						
						Выполнить(ПолучитьСтрокуВызоваОбработчика(Конвертация, "ПослеЗагрузкиОбъекта"));
						
					Иначе
						
						Выполнить(Конвертация.ПослеЗагрузкиОбъекта);
						
					КонецЕсли;
					
					НужноЗаписатьОбъект = ОбъектМодифицирован ИЛИ НужноБылоЗаписатьОбъект;
					
				Исключение
					
					УдалитьИзСтекаНеЗаписанныхОбъектов(НПП, ГНПП);
					
					ИмяОбработчика = НСтр("ru = '%1 (глобальный)'");
					ЗаписатьИнформациюОбОшибкеЗагрузкиОбработчикаПКО(54, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), 
							ИмяПравила, Источник, ТипОбъекта, Объект,
							ПодставитьПараметрыВСтроку(ИмяОбработчика, "ПослеЗагрузкиОбъекта"));
					
				КонецПопытки;
				
			КонецЕсли;
			
			// Обработчик события ПослеЗагрузкиОбъекта.
			Если ЕстьОбработчикПослеЗагрузки Тогда
				
				НужноБылоЗаписатьОбъект = НужноЗаписатьОбъект;
				ОбъектМодифицирован = Истина;
				
				Попытка
					
					Если ФлагРежимОтладкиОбработчиков Тогда
						
						Выполнить(ПолучитьСтрокуВызоваОбработчика(Правило, "ПослеЗагрузки"));
						
					Иначе
						
						Выполнить(Правило.ПослеЗагрузки);
				
					КонецЕсли;
					
					НужноЗаписатьОбъект = ОбъектМодифицирован ИЛИ НужноБылоЗаписатьОбъект;
					
				Исключение
					УдалитьИзСтекаНеЗаписанныхОбъектов(НПП, ГНПП);
					ЗаписатьИнформациюОбОшибкеЗагрузкиОбработчикаПКО(21, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
						ИмяПравила, Источник, ТипОбъекта, Объект, "ПослеЗагрузкиОбъекта");
						
				КонецПопытки;
				
			КонецЕсли;
			
			Если ИмяТипаОбъекта <> "РегистрСведений"
				И ИмяТипаОбъекта <> "Константы"
				И ИмяТипаОбъекта <> "Перечисление" Тогда
				// Проверка даты запрета для всех объектов кроме регистров сведений и констант.
				Отказ = Отказ Или ЗапретИзмененияДанныхПоДате(Объект);
			КонецЕсли;
			
			Если Отказ Тогда
				
				ДобавитьСсылкуВСписокЗагруженныхОбъектов(НППГлобальнойСсылки, НППСсылки, Неопределено);
				УдалитьИзСтекаНеЗаписанныхОбъектов(НПП, ГНПП);
				Возврат Неопределено;
				
			КонецЕсли;
			
			Если ИмяТипаОбъекта = "Документ" Тогда
				
				Если РежимЗаписи = "Проведение" Тогда
					
					РежимЗаписи = РежимЗаписиДокумента.Проведение;
					
				Иначе
					
					РежимЗаписи = ?(РежимЗаписи = "ОтменаПроведения", РежимЗаписиДокумента.ОтменаПроведения, РежимЗаписиДокумента.Запись);
					
				КонецЕсли;
				
				
				РежимПроведения = ?(РежимПроведения = "Оперативный", РежимПроведенияДокумента.Оперативный, РежимПроведенияДокумента.Неоперативный);
				

				// Если хотим провести документ помеченный на удаление, то пометку удаления снимаем ...
				Если Объект.ПометкаУдаления
					И (РежимЗаписи = РежимЗаписиДокумента.Проведение) Тогда
					
					Объект.ПометкаУдаления = Ложь;
					НужноЗаписатьОбъект = Истина;
					
					// Пометку удаления в любом случае нужно удалять.
					ПометкаУдаления = Ложь;
									
				КонецЕсли;				
				
				Попытка
					
					НужноЗаписатьОбъект = НужноЗаписатьОбъект ИЛИ (РежимЗаписи <> РежимЗаписиДокумента.Запись);
					
					РежимОбменДанными = РежимЗаписи = РежимЗаписиДокумента.Запись;
					
					ПровестиГенерациюКодаНомераПриНеобходимости(ГенерироватьНовыйНомерИлиКодЕслиНеУказан, Объект, 
						ИмяТипаОбъекта, НужноЗаписатьОбъект, РежимОбменДанными);
					
					Если НужноЗаписатьОбъект Тогда
					
						УстановитьОбменДаннымиЗагрузка(Объект, РежимОбменДанными);
						Если Объект.Проведен Тогда
							Объект.ПометкаУдаления = Ложь;
						КонецЕсли;
						
						Объект.Записать(РежимЗаписи, РежимПроведения);
						
					КонецЕсли;					
						
				Исключение
						
					// Не смогли выполнить необходимые действия для документа.
					ЗаписатьДокументВБезопасномРежиме(Объект, ТипОбъекта);
						
						
					ЗП                        = ПолучитьСтруктуруЗаписиПротокола(25,
													ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
					ЗП.ИмяПКО                 = ИмяПравила;
						
					Если Не ПустаяСтрока(Источник) Тогда
							
						ЗП.Источник           = Источник;
							
					КонецЕсли;
						
					ЗП.ТипОбъекта             = ТипОбъекта;
					ЗП.Объект                 = Строка(Объект);
					ЗаписатьВПротоколВыполнения(25, ЗП);
						
				КонецПопытки;
				
				ДобавитьСсылкуВСписокЗагруженныхОбъектов(НППГлобальнойСсылки, НППСсылки, Объект.Ссылка);
									
				УдалитьИзСтекаНеЗаписанныхОбъектов(НПП, ГНПП);
				
			ИначеЕсли ИмяТипаОбъекта <> "Перечисление" Тогда
				
				Если ИмяТипаОбъекта = "РегистрСведений" Тогда
					
					НужноЗаписатьОбъект = НЕ ЗаписыватьВИнформационнуюБазуТолькоИзмененныеОбъекты;
					
					Если СтруктураСвойств.Периодический 
						И Не ЗначениеЗаполнено(Объект.Период) Тогда
						
						Объект.Период = ТекущаяДатаСеанса();
						НужноЗаписатьОбъект = Истина;
						
					КонецЕсли;
					
					Если ЗаписыватьРегистрыНаборамиЗаписей Тогда
						
						НужноПроверитьДанныеДляВременногоНабора = 
							(ЗаписыватьВИнформационнуюБазуТолькоИзмененныеОбъекты
								И НЕ НужноЗаписатьОбъект) 
							ИЛИ НеЗамещатьОбъект;
						
						Если НужноПроверитьДанныеДляВременногоНабора Тогда
							
							ВременныйНаборЗаписей = РегистрыСведений[СтруктураСвойств.Имя].СоздатьНаборЗаписей();
							
						КонецЕсли;
						
						// Нужно отбор установить у регистра.
						Для Каждого ЭлементОтбора Из НаборЗаписей.Отбор Цикл
							
							ЭлементОтбора.Установить(Объект[ЭлементОтбора.Имя]);
							Если НужноПроверитьДанныеДляВременногоНабора Тогда
								УстановитьЗначениеЭлементаОтбора(ВременныйНаборЗаписей.Отбор, ЭлементОтбора.Имя, Объект[ЭлементОтбора.Имя]);
							КонецЕсли;
							
						КонецЦикла;
						
						Если НужноПроверитьДанныеДляВременногоНабора Тогда
							
							ВременныйНаборЗаписей.Прочитать();
							
							Если ВременныйНаборЗаписей.Количество() = 0 Тогда
								НужноЗаписатьОбъект = Истина;
							Иначе
								
								// Не хотим замещать существующий набор.
								Если НеЗамещатьОбъект Тогда
									Возврат Неопределено;
								КонецЕсли;
								
								НужноЗаписатьОбъект = Ложь;
								ТаблицаНовая = НаборЗаписей.Выгрузить(); // ТаблицаЗначений
								ТаблицаСтарая = ВременныйНаборЗаписей.Выгрузить(); 
								
								СтрокаНовая = ТаблицаНовая[0]; 
								СтрокаСтарая = ТаблицаСтарая[0]; 
								
								Для Каждого КолонкаТаблицы Из ТаблицаНовая.Колонки Цикл
									
									НужноЗаписатьОбъект = СтрокаНовая[КолонкаТаблицы.Имя] <>  СтрокаСтарая[КолонкаТаблицы.Имя];
									Если НужноЗаписатьОбъект Тогда
										Прервать;
									КонецЕсли;
									
								КонецЦикла;
								
							КонецЕсли;
							
						КонецЕсли;
						
						Объект = НаборЗаписей;
						
						Если СтруктураСвойств.Периодический Тогда
							// Проверка даты запрета изменения для набора записей.
							// Если не проходит - не записывать набор.
							Если ЗапретИзмененияДанныхПоДате(Объект) Тогда
								Возврат Неопределено;
							КонецЕсли;
						КонецЕсли;
						
					Иначе
						
						// Регистр записываем не набором записей.
						Если НеЗамещатьОбъект Или СтруктураСвойств.Периодический Тогда
							
							// Возможно мы не хотим замещать существующую запись, либо нужна проверка на дату запрета.
							ВременныйНаборЗаписей = РегистрыСведений[СтруктураСвойств.Имя].СоздатьНаборЗаписей();
							
							// Нужно отбор установить у регистра.
							Для Каждого ЭлементОтбора Из ВременныйНаборЗаписей.Отбор Цикл
							
								ЭлементОтбора.Установить(Объект[ЭлементОтбора.Имя]);
																
							КонецЦикла;
							
							ВременныйНаборЗаписей.Прочитать();
							
							Если ВременныйНаборЗаписей.Количество() > 0
								Или ЗапретИзмененияДанныхПоДате(ВременныйНаборЗаписей) Тогда
								Возврат Неопределено;
							КонецЕсли;
							
						Иначе
							// Считаем что объект следует записать.
							НужноЗаписатьОбъект = Истина;
						КонецЕсли;
						
					КонецЕсли;
					
				КонецЕсли;
				
				ЭтоСсылочныйТипОбъекта = НЕ( ИмяТипаОбъекта = "РегистрСведений"
					ИЛИ ИмяТипаОбъекта = "Константы"
					ИЛИ ИмяТипаОбъекта = "Перечисление");
					
				Если ЭтоСсылочныйТипОбъекта Тогда 	
					
					ПровестиГенерациюКодаНомераПриНеобходимости(ГенерироватьНовыйНомерИлиКодЕслиНеУказан, Объект, ИмяТипаОбъекта, НужноЗаписатьОбъект, ЗагружатьДанныеВРежимеОбмена);
					
					Если ПометкаУдаления = Неопределено Тогда
						ПометкаУдаления = Ложь;
					КонецЕсли;
					
					Если Объект.ПометкаУдаления <> ПометкаУдаления Тогда
						Объект.ПометкаУдаления = ПометкаУдаления;
						НужноЗаписатьОбъект = Истина;
					КонецЕсли;
					
				КонецЕсли;
				
				// Непосредственная запись самого объекта.
				Если НужноЗаписатьОбъект Тогда
				
					ЗаписатьОбъектВИБ(Объект, ТипОбъекта);
					
				КонецЕсли;
				
				Если ЭтоСсылочныйТипОбъекта Тогда
					
					ДобавитьСсылкуВСписокЗагруженныхОбъектов(НППГлобальнойСсылки, НППСсылки, Объект.Ссылка);
					
				КонецЕсли;
				
				УдалитьИзСтекаНеЗаписанныхОбъектов(НПП, ГНПП);
								
			КонецЕсли;
			
			Прервать;
			
		ИначеЕсли ИмяУзла = "НаборЗаписейПоследовательности" Тогда
			
			одПропустить(ФайлОбмена);
			
		ИначеЕсли ИмяУзла = "Типы" Тогда

			Если Объект = Неопределено Тогда
				
				ОбъектНайден = Ложь;
				Ссылка       = СоздатьНовыйОбъект(ТипОбъекта, СвойстваПоиска, Объект, , , , НППСсылки, НППГлобальнойСсылки, ПараметрыОбъекта);
								
			КонецЕсли; 

			ОписаниеТиповОбъекта = ЗагрузитьТипыОбъекта(ФайлОбмена);

			Если ОписаниеТиповОбъекта <> Неопределено Тогда
				
				Объект.ТипЗначения = ОписаниеТиповОбъекта;
				
			КонецЕсли; 
			
		Иначе
			
			ЗаписатьВПротоколВыполнения(9);
			Прервать;
			
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат Объект;

КонецФункции

// Выполняет проверку на наличие запрета загрузки по дате.
//
// Параметры:
//   ЭлементДанных	  - СправочникОбъект, ДокументОбъект, РегистрСведенийНаборЗаписей и др. данные.
//                      Данные, которые были зачитаны из сообщения обмена, но еще не были записаны в ИБ.
//   ПолучениеЭлемента - ПолучениеЭлементаДанных.
//
// Возвращаемое значение:
//   Булево - Истина - установлена дата запрета изменения и загружаемый объект имеет дату меньше установленной, иначе Ложь.
//
Функция ЗапретИзмененияДанныхПоДате(ЭлементДанных)
	
	ИзменениеЗапрещено = Ложь;
	
	Если МодульДатыЗапретаИзменения <> Неопределено
		И Не Метаданные.Константы.Содержит(ЭлементДанных.Метаданные()) Тогда
		Попытка
			Если МодульДатыЗапретаИзменения.ИзменениеЗапрещено(ЭлементДанных) Тогда
				ИзменениеЗапрещено = Истина;
			КонецЕсли;
		Исключение
			ИзменениеЗапрещено = Ложь;
		КонецПопытки;
	КонецЕсли;
	
	ЭлементДанных.ДополнительныеСвойства.Вставить("ПропуститьПроверкуЗапретаИзменения");
	
	Возврат ИзменениеЗапрещено;
	
КонецФункции

Функция ПроверитьСуществованиеСсылки(Ссылка, Менеджер, НайденныйОбъектПоУникальномуИдентификатору,
	СтрокаЗапросаПоискаПоУникальномуИдентификатору)
	
	Попытка
			
		Если ПустаяСтрока(СтрокаЗапросаПоискаПоУникальномуИдентификатору) Тогда
			
			НайденныйОбъектПоУникальномуИдентификатору = Ссылка.ПолучитьОбъект();
			
			Если НайденныйОбъектПоУникальномуИдентификатору = Неопределено Тогда
			
				Возврат Менеджер.ПустаяСсылка();
				
			КонецЕсли;
			
		Иначе
			// Это режим поиска по ссылке - достаточно сделать запрос к информационной базе
			// шаблон для запроса СтруктураСвойств.СтрокаПоиска.
			
			Запрос = Новый Запрос();
			Запрос.Текст = СтрокаЗапросаПоискаПоУникальномуИдентификатору + "  Ссылка = &Ссылка ";
			Запрос.УстановитьПараметр("Ссылка", Ссылка);
			
			РезультатЗапроса = Запрос.Выполнить();
			
			Если РезультатЗапроса.Пустой() Тогда
			
				Возврат Менеджер.ПустаяСсылка();
				
			КонецЕсли;
			
		КонецЕсли;
		
		Возврат Ссылка;	
		
	Исключение
			
		Возврат Менеджер.ПустаяСсылка();
		
	КонецПопытки;
	
КонецФункции

Функция ВычислитьВыражение(Знач Выражение)
	
	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	// Вызов ВычислитьВБезопасномРежиме не требуется, т.к. безопасный режим устанавливается без использования средств БСП.
	Возврат Вычислить(Выражение);
	
КонецФункции

Функция ЕстьРеквизитИлиСвойствоОбъекта(Объект, ИмяРеквизита)
	
	КлючУникальности   = Новый УникальныйИдентификатор;
	СтруктураРеквизита = Новый Структура(ИмяРеквизита, КлючУникальности);
	ЗаполнитьЗначенияСвойств(СтруктураРеквизита, Объект);
	
	Возврат СтруктураРеквизита[ИмяРеквизита] <> КлючУникальности;
	
КонецФункции

// Параметры:
//   Отбор - Отбор - произвольный отбор.
//   КлючЭлемента - Строка - имя элемента отбора.
//   ЗначениеЭлемента - Произвольный - значение элемента отбора.
//
Процедура УстановитьЗначениеЭлементаОтбора(Отбор, КлючЭлемента, ЗначениеЭлемента)
	
	ЭлементОтбора = Отбор.Найти(КлючЭлемента);
	Если ЭлементОтбора <> Неопределено Тогда
		ЭлементОтбора.Установить(ЗначениеЭлемента);
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ПроцедурыВыгрузкиДанных

Функция ПолучитьНаборДвиженийДокумента(СсылкаНаДокумент, ВидИсточника, ИмяРегистра)
	
	Если ВидИсточника = "НаборДвиженийРегистраНакопления" Тогда
		
		НаборДвиженийДокумента = РегистрыНакопления[ИмяРегистра].СоздатьНаборЗаписей();
		
	ИначеЕсли ВидИсточника = "НаборДвиженийРегистраСведений" Тогда
		
		НаборДвиженийДокумента = РегистрыСведений[ИмяРегистра].СоздатьНаборЗаписей();
		
	ИначеЕсли ВидИсточника = "НаборДвиженийРегистраБухгалтерии" Тогда
		
		НаборДвиженийДокумента = РегистрыБухгалтерии[ИмяРегистра].СоздатьНаборЗаписей();
		
	ИначеЕсли ВидИсточника = "НаборДвиженийРегистраРасчета" Тогда	
		
		НаборДвиженийДокумента = РегистрыРасчета[ИмяРегистра].СоздатьНаборЗаписей();
		
	Иначе
		
		Возврат Неопределено;
		
	КонецЕсли;
	
	УстановитьЗначениеЭлементаОтбора(НаборДвиженийДокумента.Отбор, "Регистратор", СсылкаНаДокумент);
	НаборДвиженийДокумента.Прочитать();
	
	Возврат НаборДвиженийДокумента;
	
КонецФункции

Процедура ВыполнитьЗаписьСтруктурыВXML(СтруктураДанных, УзелКоллекцииСвойств)
	
	УзелКоллекцииСвойств.ЗаписатьНачалоЭлемента("Свойство");
	
	Для Каждого ЭлементКоллекции Из СтруктураДанных Цикл
		
		Если ЭлементКоллекции.Ключ = "Выражение"
			ИЛИ ЭлементКоллекции.Ключ = "Значение"
			ИЛИ ЭлементКоллекции.Ключ = "Нпп"
			ИЛИ ЭлементКоллекции.Ключ = "ГНпп" Тогда
			
			одЗаписатьЭлемент(УзелКоллекцииСвойств, ЭлементКоллекции.Ключ, ЭлементКоллекции.Значение);
			
		ИначеЕсли ЭлементКоллекции.Ключ = "Ссылка" Тогда
			
			УзелКоллекцииСвойств.ЗаписатьБезОбработки(ЭлементКоллекции.Значение);
			
		Иначе
			
			УстановитьАтрибут(УзелКоллекцииСвойств, ЭлементКоллекции.Ключ, ЭлементКоллекции.Значение);
			
		КонецЕсли;
		
	КонецЦикла;
	
	УзелКоллекцииСвойств.ЗаписатьКонецЭлемента();		
	
КонецПроцедуры

Процедура СоздатьОбъектыДляЗаписиДанныхВXML(СтруктураДанных, УзелСвойства, НуженУзелXML, ИмяУзла, НаименованиеУзлаXML = "Свойство")
	
	Если НуженУзелXML Тогда
		
		УзелСвойства = СоздатьУзел(НаименованиеУзлаXML);
		УстановитьАтрибут(УзелСвойства, "Имя", ИмяУзла);
		
	Иначе
		
		СтруктураДанных = Новый Структура("Имя", ИмяУзла);	
		
	КонецЕсли;		
	
КонецПроцедуры

Процедура ДобавитьАтрибутДляЗаписиВXML(СтруктураУзлаСвойств, УзелСвойства, ИмяАтрибута, ЗначениеАтрибута)
	
	Если СтруктураУзлаСвойств <> Неопределено Тогда
		СтруктураУзлаСвойств.Вставить(ИмяАтрибута, ЗначениеАтрибута);
	Иначе
		УстановитьАтрибут(УзелСвойства, ИмяАтрибута, ЗначениеАтрибута);
	КонецЕсли;
	
КонецПроцедуры

Процедура ПроизвестиЗаписьДанныхВГоловнойУзел(УзелКоллекцииСвойств, СтруктураУзлаСвойств, УзелСвойства)
	
	Если СтруктураУзлаСвойств <> Неопределено Тогда
		ВыполнитьЗаписьСтруктурыВXML(СтруктураУзлаСвойств, УзелКоллекцииСвойств);
	Иначе
		ДобавитьПодчиненный(УзелКоллекцииСвойств, УзелСвойства);
	КонецЕсли;
	
КонецПроцедуры

// Формирует узлы свойств объекта приемника в соответствии с указанной коллекцией правил конвертации свойств.
//
// Параметры:
//  Источник		     - произвольный источник данных.
//  Приемник		     - ЗаписьXML - xml-узел объекта приемника.
//  ВходящиеДанные	     - произвольные вспомогательные данные, передаваемые правилу
//                         для выполнения конвертации.
//  ИсходящиеДанные      - произвольные вспомогательные данные, передаваемые правилам
//                         конвертации объектов свойств.
//  ПКО				     - ссылка на правило конвертации объектов (родитель коллекции правил конвертации свойств).
//  ПКГС                 - ссылка на правило конвертации группы свойств.
//  УзелКоллекцииСвойств - ЗаписьXML - xml-узел коллекции свойств.
// 
Процедура ВыгрузитьГруппуСвойств(Источник, Приемник, ВходящиеДанные, ИсходящиеДанные, ПКО, ПКГС, УзелКоллекцииСвойств, 
	ВыгрузитьТолькоСсылку, СписокВременныхФайлов = Неопределено)
	
	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	КоллекцияОбъектов = Неопределено;
	НеЗамещать        = ПКГС.НеЗамещать;
	НеОчищать         = Ложь;
	ВыгружатьГруппуЧерезФайл = ПКГС.ВыгружатьГруппуЧерезФайл;
	
	// Обработчик ПередОбработкойВыгрузки
	Если ПКГС.ЕстьОбработчикПередОбработкойВыгрузки Тогда
		
		Отказ = Ложь;
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКГС, "ПередОбработкойВыгрузки"));
				
			Иначе
				
				Выполнить(ПКГС.ПередОбработкойВыгрузки);
				
			КонецЕсли;
			
		Исключение
			
			ЗаписатьИнформациюОбОшибкеОбработчикиПКС(48, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				ПКО, ПКГС, Источник, "ПередОбработкойВыгрузкиГруппыСвойств",, Ложь);
		
		КонецПопытки;
		
		Если Отказ Тогда // Отказ от обработки группы свойств.
			
			Возврат;
			
		КонецЕсли;
		
	КонецЕсли;

	
    ВидПриемника = ПКГС.ВидПриемника;
	ВидИсточника = ПКГС.ВидИсточника;
	
	
    // Создание узла коллекции подчиненных объектов.
	СтруктураУзлаСвойств = Неопределено;
	УзелКоллекцииОбъектов = Неопределено;
	ИмяГоловногоУзла = "";
	
	Если ВидПриемника = "ТабличнаяЧасть" Тогда
		
		ИмяГоловногоУзла = "ТабличнаяЧасть";
		
		СоздатьОбъектыДляЗаписиДанныхВXML(СтруктураУзлаСвойств, УзелКоллекцииОбъектов, ИСТИНА, ПКГС.Приемник, ИмяГоловногоУзла);
		
		Если НеЗамещать Тогда
			
			ДобавитьАтрибутДляЗаписиВXML(СтруктураУзлаСвойств, УзелКоллекцииОбъектов, "НеЗамещать", "true");
						
		КонецЕсли;
		
		Если НеОчищать Тогда
			
			ДобавитьАтрибутДляЗаписиВXML(СтруктураУзлаСвойств, УзелКоллекцииОбъектов, "НеОчищать", "true");
						
		КонецЕсли;
		
	ИначеЕсли ВидПриемника = "ПодчиненныйСправочник" Тогда
				
		
	ИначеЕсли ВидПриемника = "НаборЗаписейПоследовательности" Тогда
		
		ИмяГоловногоУзла = "НаборЗаписей";
		
		СоздатьОбъектыДляЗаписиДанныхВXML(СтруктураУзлаСвойств, УзелКоллекцииОбъектов, ИСТИНА, ПКГС.Приемник, ИмяГоловногоУзла);
		
	ИначеЕсли СтрНайти(ВидПриемника, "НаборДвижений") > 0 Тогда
		
		ИмяГоловногоУзла = "НаборЗаписей";
		
		СоздатьОбъектыДляЗаписиДанныхВXML(СтруктураУзлаСвойств, УзелКоллекцииОбъектов, ИСТИНА, ПКГС.Приемник, ИмяГоловногоУзла);
		
		Если НеЗамещать Тогда
			
			ДобавитьАтрибутДляЗаписиВXML(СтруктураУзлаСвойств, УзелКоллекцииОбъектов, "НеЗамещать", "true");
						
		КонецЕсли;
		
		Если НеОчищать Тогда
			
			ДобавитьАтрибутДляЗаписиВXML(СтруктураУзлаСвойств, УзелКоллекцииОбъектов, "НеОчищать", "true");
						
		КонецЕсли;
		
	Иначе  // это простая группировка
		
		ВыгрузитьСвойства(Источник, Приемник, ВходящиеДанные, ИсходящиеДанные, ПКО, ПКГС.ПравилаГруппы, 
		     УзелКоллекцииСвойств, , , ПКО.НеВыгружатьОбъектыСвойствПоСсылкам ИЛИ ВыгрузитьТолькоСсылку);
			
		Если ПКГС.ЕстьОбработчикПослеОбработкиВыгрузки Тогда
			
			Попытка
				
				Если ФлагРежимОтладкиОбработчиков Тогда
					
					Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКГС, "ПослеОбработкиВыгрузки"));
					
				Иначе
					
					Выполнить(ПКГС.ПослеОбработкиВыгрузки);
			
				КонецЕсли;
				
			Исключение
				
				ЗаписатьИнформациюОбОшибкеОбработчикиПКС(49, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
					ПКО, ПКГС, Источник, "ПослеОбработкиВыгрузкиГруппыСвойств",, Ложь);
				
			КонецПопытки;
			
		КонецЕсли;
		
		Возврат;
		
	КонецЕсли;
	
	// Получение коллекции подчиненных объектов.
	
	Если КоллекцияОбъектов <> Неопределено Тогда
		
		// Инициализировали коллекцию в обработчике ПередОбработкой.
		
	ИначеЕсли ПКГС.ПолучитьИзВходящихДанных Тогда
		
		Попытка
			
			КоллекцияОбъектов = ВходящиеДанные[ПКГС.Приемник];
			
			Если ТипЗнч(КоллекцияОбъектов) = Тип("РезультатЗапроса") Тогда
				
				КоллекцияОбъектов = КоллекцияОбъектов.Выгрузить();
				
			КонецЕсли;
			
		Исключение
			
			ЗаписатьИнформациюОбОшибкеОбработчикиПКС(66, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				ПКО, ПКГС, Источник,,,Ложь);
			
			Возврат;
		КонецПопытки;
		
	ИначеЕсли ВидИсточника = "ТабличнаяЧасть" Тогда
		
		КоллекцияОбъектов = Источник[ПКГС.Источник];
		
		Если ТипЗнч(КоллекцияОбъектов) = Тип("РезультатЗапроса") Тогда
			
			КоллекцияОбъектов = КоллекцияОбъектов.Выгрузить();
			
		КонецЕсли;
		
	ИначеЕсли ВидИсточника = "ПодчиненныйСправочник" Тогда
		
	ИначеЕсли СтрНайти(ВидИсточника, "НаборДвижений") > 0 Тогда
		
		КоллекцияОбъектов = ПолучитьНаборДвиженийДокумента(Источник, ВидИсточника, ПКГС.Источник);
				
	ИначеЕсли ПустаяСтрока(ПКГС.Источник) Тогда
		
		КоллекцияОбъектов = Источник[ПКГС.Приемник];
		
		Если ТипЗнч(КоллекцияОбъектов) = Тип("РезультатЗапроса") Тогда
			
			КоллекцияОбъектов = КоллекцияОбъектов.Выгрузить();
			
		КонецЕсли;
		
	КонецЕсли;
	
	ВыгружатьГруппуЧерезФайл = ВыгружатьГруппуЧерезФайл Или (КоллекцияОбъектов.Количество() > 1000);
	ВыгружатьГруппуЧерезФайл = ВыгружатьГруппуЧерезФайл И (НепосредственноеЧтениеВИБПриемнике = Ложь);
	
	Если ВыгружатьГруппуЧерезФайл Тогда
		
		ПКГС.НуженУзелXMLПриВыгрузке = Ложь;
		
		Если СписокВременныхФайлов = Неопределено Тогда
			СписокВременныхФайлов = Новый Массив;
		КонецЕсли;
		
		ВременныйФайлЗаписей = ЗаписьТекстаВоВременныйФайл(СписокВременныхФайлов);
		
		ИнформацияДляЗаписиВФайл = УзелКоллекцииОбъектов.Закрыть();
		ВременныйФайлЗаписей.ЗаписатьСтроку(ИнформацияДляЗаписиВФайл);
		
	КонецЕсли;
	
	Для Каждого ОбъектКоллекции Из КоллекцияОбъектов Цикл
		
		// Обработчик ПередВыгрузкой
		Если ПКГС.ЕстьОбработчикПередВыгрузкой Тогда
			
			Отказ = Ложь;
			
			Попытка
				
				Если ФлагРежимОтладкиОбработчиков Тогда
					
					Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКГС, "ПередВыгрузкой"));
					
				Иначе
					
					Выполнить(ПКГС.ПередВыгрузкой);
					
				КонецЕсли;
				
			Исключение
				
				ЗаписатьИнформациюОбОшибкеОбработчикиПКС(50, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
					ПКО, ПКГС, Источник, "ПередВыгрузкойГруппыСвойств",, Ложь);
				
				Прервать;
				
			КонецПопытки;
			
			Если Отказ Тогда	//	Отказ от выгрузки подчиненного объекта.
				
				Продолжить;
				
			КонецЕсли;
			
		КонецЕсли;
		
		// Обработчик ПриВыгрузке
		
		Если ПКГС.НуженУзелXMLПриВыгрузке ИЛИ ВыгружатьГруппуЧерезФайл Тогда
			УзелОбъектаКоллекции = СоздатьУзел("Запись");
		Иначе
			УзелКоллекцииОбъектов.ЗаписатьНачалоЭлемента("Запись");
			УзелОбъектаКоллекции = УзелКоллекцииОбъектов;
		КонецЕсли;
		
		СтандартнаяОбработка	= Истина;
		
		Если ПКГС.ЕстьОбработчикПриВыгрузке Тогда
			
			Попытка
				
				Если ФлагРежимОтладкиОбработчиков Тогда
					
					Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКГС, "ПриВыгрузке"));
					
				Иначе
					
					Выполнить(ПКГС.ПриВыгрузке);
					
				КонецЕсли;
				
			Исключение
				
				ЗаписатьИнформациюОбОшибкеОбработчикиПКС(51, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
					ПКО, ПКГС, Источник, "ПриВыгрузкеГруппыСвойств",, Ложь);
				
				Прервать;
				
			КонецПопытки;
			
		КонецЕсли;

		//	Выгрузка свойств объекта коллекции.
		
		Если СтандартнаяОбработка Тогда
			
			Если ПКГС.ПравилаГруппы.Количество() > 0 Тогда
				
		 		ВыгрузитьСвойства(Источник, Приемник, ВходящиеДанные, ИсходящиеДанные, ПКО, ПКГС.ПравилаГруппы, 
		 			УзелОбъектаКоллекции, ОбъектКоллекции, , ПКО.НеВыгружатьОбъектыСвойствПоСсылкам ИЛИ ВыгрузитьТолькоСсылку);
				
			КонецЕсли;
			
		КонецЕсли;
		
		// Обработчик ПослеВыгрузки
		
		Если ПКГС.ЕстьОбработчикПослеВыгрузки Тогда
			
			Отказ = Ложь;
			
			Попытка
				
				Если ФлагРежимОтладкиОбработчиков Тогда
					
					Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКГС, "ПослеВыгрузки"));
					
				Иначе
					
					Выполнить(ПКГС.ПослеВыгрузки);
					
				КонецЕсли;
				
			Исключение
				
				ЗаписатьИнформациюОбОшибкеОбработчикиПКС(52, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
					ПКО, ПКГС, Источник, "ПослеВыгрузкиГруппыСвойств",, Ложь);
				
				Прервать;
				
			КонецПопытки;
			
			Если Отказ Тогда	//	Отказ от выгрузки подчиненного объекта.
				
				Продолжить;
				
			КонецЕсли;
			
		КонецЕсли;
		
		Если ПКГС.НуженУзелXMLПриВыгрузке Тогда
			ДобавитьПодчиненный(УзелКоллекцииОбъектов, УзелОбъектаКоллекции);
		КонецЕсли;
		
		// Заполняем файл объектами узла.
		Если ВыгружатьГруппуЧерезФайл Тогда
			
			УзелОбъектаКоллекции.ЗаписатьКонецЭлемента();
			ИнформацияДляЗаписиВФайл = УзелОбъектаКоллекции.Закрыть();
			ВременныйФайлЗаписей.ЗаписатьСтроку(ИнформацияДляЗаписиВФайл);
			
		Иначе
			
			Если Не ПКГС.НуженУзелXMLПриВыгрузке Тогда
				
				УзелКоллекцииОбъектов.ЗаписатьКонецЭлемента();
				
			КонецЕсли;
			
		КонецЕсли;
		
	КонецЦикла;
	
	
    // Обработчик ПослеОбработкиВыгрузки

	Если ПКГС.ЕстьОбработчикПослеОбработкиВыгрузки Тогда
		
		Отказ = Ложь;
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКГС, "ПослеОбработкиВыгрузки"));
				
			Иначе
				
				Выполнить(ПКГС.ПослеОбработкиВыгрузки);
				
			КонецЕсли;
			
		Исключение
			
			ЗаписатьИнформациюОбОшибкеОбработчикиПКС(49, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				ПКО, ПКГС, Источник, "ПослеОбработкиВыгрузкиГруппыСвойств",, Ложь);
			
		КонецПопытки;
		
		Если Отказ Тогда //	Отказ от записи коллекции подчиненных объектов.
			
			Возврат;
			
		КонецЕсли;
		
	КонецЕсли;
	
	Если ВыгружатьГруппуЧерезФайл Тогда
		ВременныйФайлЗаписей.ЗаписатьСтроку("</" + ИмяГоловногоУзла + ">"); // закрыть узел
		ВременныйФайлЗаписей.Закрыть(); 	// закрыть файл явно
	Иначе
		ПроизвестиЗаписьДанныхВГоловнойУзел(УзелКоллекцииСвойств, СтруктураУзлаСвойств, УзелКоллекцииОбъектов);
	КонецЕсли;

КонецПроцедуры

Процедура ПолучитьЗначениеСвойства(Значение, ОбъектКоллекции, ПКО, ПКС, ВходящиеДанные, Источник)
	
	Если Значение <> Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Если ПКС.ПолучитьИзВходящихДанных Тогда
			
			ОбъектДляПолученияДанных = ВходящиеДанные;
			
			Если Не ПустаяСтрока(ПКС.Приемник) Тогда
			
				ИмяСвойства = ПКС.Приемник;
				
			Иначе
				
				ИмяСвойства = ПКС.ИмяПараметраДляПередачи;
				
			КонецЕсли;
			
			КодОшибки = ?(ОбъектКоллекции <> Неопределено, 67, 68);
	
	ИначеЕсли ОбъектКоллекции <> Неопределено Тогда
		
		ОбъектДляПолученияДанных = ОбъектКоллекции;
		
		Если Не ПустаяСтрока(ПКС.Источник) Тогда
			
			ИмяСвойства = ПКС.Источник;
			КодОшибки = 16;
						
		Иначе
			
			ИмяСвойства = ПКС.Приемник;
			КодОшибки = 17;
			
		КонецЕсли;
		
	Иначе
		
		ОбъектДляПолученияДанных = Источник;
		
		Если Не ПустаяСтрока(ПКС.Источник) Тогда
		
			ИмяСвойства = ПКС.Источник;
			КодОшибки = 13;
		
		Иначе
			
			ИмяСвойства = ПКС.Приемник;
			КодОшибки = 14;
			
		КонецЕсли;
		
	КонецЕсли;
	
	Попытка
		
		Значение = ОбъектДляПолученияДанных[ИмяСвойства];
		
	Исключение
		
		Если КодОшибки <> 14 Тогда
			ЗаписатьИнформациюОбОшибкеОбработчикиПКС(КодОшибки, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				ПКО, ПКС, Источник, "");
		КонецЕсли;
		
	КонецПопытки;
	
КонецПроцедуры

Процедура ВыгрузитьТипСвойстваЭлемента(УзелСвойства, ТипСвойства)
	
	УстановитьАтрибут(УзелСвойства, "Тип", ТипСвойства);	
	
КонецПроцедуры

Процедура ВыгрузитьСубконто(Источник,
							Приемник,
							ВходящиеДанные,
							ИсходящиеДанные,
							ПКО,
							ПКС,
							УзелКоллекцииСвойств ,
							ОбъектКоллекции,
							Знач ВыгрузитьТолькоСсылку)
	
	//
	// Переменные-заглушки для поддержки механизма отладки кода обработчиков событий
	// (поддержка интерфейса процедуры-обертки обработчика).
	Перем ТипПриемника, Пусто, Выражение, НеЗамещать, УзелСвойства, ПКОСвойств;
	
	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	// Инициализация значения
	Значение = Неопределено;
	ИмяПКО = "";
	ИмяПКОВидСубконто = "";
	
	// Обработчик ПередВыгрузкой
	Если ПКС.ЕстьОбработчикПередВыгрузкой Тогда
		
		Отказ = Ложь;
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКС, "ПередВыгрузкой"));
				
			Иначе
				
				Выполнить(ПКС.ПередВыгрузкой);
				
			КонецЕсли;
			
		Исключение
			
			ЗаписатьИнформациюОбОшибкеОбработчикиПКС(55, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				ПКО, ПКС, Источник, "ПередВыгрузкойСвойства", Значение);
				
		КонецПопытки;
			
		Если Отказ Тогда // Отказ от выгрузки
			
			Возврат;
			
		КонецЕсли;
		
	КонецЕсли;
	
	ПолучитьЗначениеСвойства(Значение, ОбъектКоллекции, ПКО, ПКС, ВходящиеДанные, Источник);
	
	Если ПКС.ПриводитьКДлине <> 0 Тогда
		
		ВыполнитьПриведениеЗначенияКДлине(Значение, ПКС);
		
	КонецЕсли;
		
	Для каждого КлючИЗначение Из Значение Цикл
		
		ВидСубконто = КлючИЗначение.Ключ;
		Субконто = КлючИЗначение.Значение;
		ИмяПКО = "";
		
		// Обработчик ПриВыгрузке
		Если ПКС.ЕстьОбработчикПриВыгрузке Тогда
			
			Отказ = Ложь;
			
			Попытка
				
				Если ФлагРежимОтладкиОбработчиков Тогда
					
					Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКС, "ПриВыгрузке"));
					
				Иначе
					
					Выполнить(ПКС.ПриВыгрузке);
					
				КонецЕсли;
				
			Исключение
				
				ЗаписатьИнформациюОбОшибкеОбработчикиПКС(56, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
					ПКО, ПКС, Источник, "ПриВыгрузкеСвойства", Значение);
				
			КонецПопытки;
				
			Если Отказ Тогда // Отказ от выгрузки субконто
				
				Продолжить;
				
			КонецЕсли;
			
		КонецЕсли;
		
		Если Субконто = Неопределено
			ИЛИ НайтиПравило(Субконто, ИмяПКО) = Неопределено Тогда
			
			Продолжить;
			
		КонецЕсли;
			
		УзелСубконто = СоздатьУзел(ПКС.Приемник);
		
		// Ключ
		УзелСвойства = СоздатьУзел("Свойство");
		
		Если ПустаяСтрока(ИмяПКОВидСубконто) Тогда
			
			ПКОКлюч = НайтиПравило(ВидСубконто, ИмяПКОВидСубконто);
			
		Иначе
			
			ПКОКлюч = НайтиПравило(, ИмяПКОВидСубконто);
			
		КонецЕсли;
		
		УстановитьАтрибут(УзелСвойства, "Имя", "Ключ");
		ВыгрузитьТипСвойстваЭлемента(УзелСвойства, ПКОКлюч.Приемник);
			
		УзелСсылки = ВыгрузитьПоПравилу(ВидСубконто,, ИсходящиеДанные,, ИмяПКОВидСубконто,, ВыгрузитьТолькоСсылку, ПКОКлюч);
			
		Если УзелСсылки <> Неопределено Тогда
			
			ЭтоПравилоСГлобальнойВыгрузкой = Ложь;
			ТипУзлаСсылки = ТипЗнч(УзелСсылки);
			ДобавитьСвойстваДляВыгрузки(УзелСсылки, ТипУзлаСсылки, УзелСвойства, ЭтоПравилоСГлобальнойВыгрузкой);
			
		КонецЕсли;
		
		ДобавитьПодчиненный(УзелСубконто, УзелСвойства);
		
		// Значение
		УзелСвойства = СоздатьУзел("Свойство");
		
		ПКОЗначение = НайтиПравило(Субконто, ИмяПКО);
		
		ТипПриемника = ПКОЗначение.Приемник;
		
		ЭтоNULL = Ложь;
		Пусто = одПустое(Субконто, ЭтоNULL);
		
		Если Пусто Тогда
			
			Если ЭтоNULL 
				Или Субконто = Неопределено Тогда
				
				Продолжить;
				
			КонецЕсли;
			
			Если ПустаяСтрока(ТипПриемника) Тогда
				
				ТипПриемника = ОпределитьТипДанныхДляПриемника(Субконто);
				
			КонецЕсли;
			
			УстановитьАтрибут(УзелСвойства, "Имя", "Значение");
			
			Если Не ПустаяСтрока(ТипПриемника) Тогда
				УстановитьАтрибут(УзелСвойства, "Тип", ТипПриемника);
			КонецЕсли;
			
			// Если тип множественный, то возможно это пустая ссылка и выгрузить ее нужно именно с указанием типа.
			одЗаписатьЭлемент(УзелСвойства, "Пусто");
			
			ДобавитьПодчиненный(УзелСубконто, УзелСвойства);
			
		Иначе
			
			ЭтоПравилоСГлобальнойВыгрузкой = Ложь;
			УзелСсылки = ВыгрузитьПоПравилу(Субконто,, ИсходящиеДанные, , ИмяПКО, , ВыгрузитьТолькоСсылку, ПКОЗначение, ЭтоПравилоСГлобальнойВыгрузкой);
			
			УстановитьАтрибут(УзелСвойства, "Имя", "Значение");
			ВыгрузитьТипСвойстваЭлемента(УзелСвойства, ТипПриемника);
			
			Если УзелСсылки = Неопределено Тогда
				
				Продолжить;
				
			КонецЕсли;
			
			ТипУзлаСсылки = ТипЗнч(УзелСсылки);
			
			ДобавитьСвойстваДляВыгрузки(УзелСсылки, ТипУзлаСсылки, УзелСвойства, ЭтоПравилоСГлобальнойВыгрузкой);
			
			ДобавитьПодчиненный(УзелСубконто, УзелСвойства);
			
		КонецЕсли;
		
		// Обработчик ПослеВыгрузки
		Если ПКС.ЕстьОбработчикПослеВыгрузки Тогда
			
			Отказ = Ложь;
			
			Попытка
				
				Если ФлагРежимОтладкиОбработчиков Тогда
					
					Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКС, "ПослеВыгрузки"));
					
				Иначе
					
					Выполнить(ПКС.ПослеВыгрузки);
					
				КонецЕсли;
					
			Исключение
					
				ЗаписатьИнформациюОбОшибкеОбработчикиПКС(57, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
					ПКО, ПКС, Источник, "ПослеВыгрузкиСвойства", Значение);
					
			КонецПопытки;
			
			Если Отказ Тогда // Отказ от выгрузки
				
				Продолжить;
				
			КонецЕсли;
			
		КонецЕсли;
		
		ДобавитьПодчиненный(УзелКоллекцииСвойств, УзелСубконто);
		
	КонецЦикла;
	
КонецПроцедуры

Процедура ДобавитьСвойстваДляВыгрузки(УзелСсылки, ТипУзлаСсылки, УзелСвойства, ЭтоПравилоСГлобальнойВыгрузкой)
	
	Если ТипУзлаСсылки = одТипСтрока Тогда
				
		Если СтрНайти(УзелСсылки, "<Ссылка") > 0 Тогда
					
			УзелСвойства.ЗаписатьБезОбработки(УзелСсылки);
					
		Иначе
			
			одЗаписатьЭлемент(УзелСвойства, "Значение", УзелСсылки);
					
		КонецЕсли;
				
	ИначеЕсли ТипУзлаСсылки = одТипЧисло Тогда
		
		Если ЭтоПравилоСГлобальнойВыгрузкой Тогда
		
			одЗаписатьЭлемент(УзелСвойства, "ГНпп", УзелСсылки);
			
		Иначе     		
			
			одЗаписатьЭлемент(УзелСвойства, "Нпп", УзелСсылки);
			
		КонецЕсли;
				
	Иначе
				
		ДобавитьПодчиненный(УзелСвойства, УзелСсылки);
				
	КонецЕсли;	
	
КонецПроцедуры

Процедура ДобавитьЗначениеСвойстваВУзел(Значение, ТипЗначения, ТипПриемника, УзелСвойства, СвойствоУстановлено)
	
	СвойствоУстановлено = Истина;
		
	Если ТипЗначения = одТипСтрока Тогда
				
		Если ТипПриемника = "Строка"  Тогда
		ИначеЕсли ТипПриемника = "Число"  Тогда
					
			Значение = Число(Значение);
					
		ИначеЕсли ТипПриемника = "Булево"  Тогда
					
			Значение = Булево(Значение);
					
		ИначеЕсли ТипПриемника = "Дата"  Тогда
					
			Значение = Дата(Значение);
					
		ИначеЕсли ТипПриемника = "ХранилищеЗначения"  Тогда
					
			Значение = Новый ХранилищеЗначения(Значение);
					
		ИначеЕсли ТипПриемника = "УникальныйИдентификатор" Тогда
					
			Значение = Новый УникальныйИдентификатор(Значение);
					
		ИначеЕсли ПустаяСтрока(ТипПриемника) Тогда
					
			УстановитьАтрибут(УзелСвойства, "Тип", "Строка");
					
		КонецЕсли;
				
		одЗаписатьЭлемент(УзелСвойства, "Значение", Значение);
				
	ИначеЕсли ТипЗначения = одТипЧисло Тогда
				
		Если ТипПриемника = "Число"  Тогда
		ИначеЕсли ТипПриемника = "Булево"  Тогда
					
			Значение = Булево(Значение);
					
		ИначеЕсли ТипПриемника = "Строка"  Тогда
		ИначеЕсли ПустаяСтрока(ТипПриемника) Тогда
					
			УстановитьАтрибут(УзелСвойства, "Тип", "Число");
					
		Иначе
					
			Возврат;
					
		КонецЕсли;
				
		одЗаписатьЭлемент(УзелСвойства, "Значение", Значение);
				
	ИначеЕсли ТипЗначения = одТипДата Тогда
				
		Если ТипПриемника = "Дата"  Тогда
		ИначеЕсли ТипПриемника = "Строка"  Тогда
					
			Значение = Лев(Строка(Значение), 10);
					
		ИначеЕсли ПустаяСтрока(ТипПриемника) Тогда
					
			УстановитьАтрибут(УзелСвойства, "Тип", "Дата");
					
		Иначе
					
			Возврат;
					
		КонецЕсли;
				
		одЗаписатьЭлемент(УзелСвойства, "Значение", Значение);
				
	ИначеЕсли ТипЗначения = одТипБулево Тогда
				
		Если ТипПриемника = "Булево"  Тогда
		ИначеЕсли ТипПриемника = "Число"  Тогда
					
			Значение = Число(Значение);
					
		ИначеЕсли ПустаяСтрока(ТипПриемника) Тогда
					
			УстановитьАтрибут(УзелСвойства, "Тип", "Булево");
					
		Иначе
					
			Возврат;
					
		КонецЕсли;
				
		одЗаписатьЭлемент(УзелСвойства, "Значение", Значение);
				
	ИначеЕсли ТипЗначения = одТипХранилищеЗначения Тогда
				
		Если ПустаяСтрока(ТипПриемника) Тогда
					
			УстановитьАтрибут(УзелСвойства, "Тип", "ХранилищеЗначения");
					
		ИначеЕсли ТипПриемника <> "ХранилищеЗначения"  Тогда
					
			Возврат;
					
		КонецЕсли;
				
		одЗаписатьЭлемент(УзелСвойства, "Значение", Значение);
				
	ИначеЕсли ТипЗначения = одТипУникальныйИдентификатор Тогда
		
		Если ТипПриемника = "УникальныйИдентификатор" Тогда
		ИначеЕсли ТипПриемника = "Строка"  Тогда
					
			Значение = Строка(Значение);
					
		ИначеЕсли ПустаяСтрока(ТипПриемника) Тогда
					
			УстановитьАтрибут(УзелСвойства, "Тип", "УникальныйИдентификатор");
					
		Иначе
					
			Возврат;
					
		КонецЕсли;
		
		одЗаписатьЭлемент(УзелСвойства, "Значение", Значение);
		
	ИначеЕсли ТипЗначения = одТипВидДвиженияНакопления Тогда
				
		одЗаписатьЭлемент(УзелСвойства, "Значение", Строка(Значение));		
		
	Иначе	
		
		СвойствоУстановлено = Ложь;
		
	КонецЕсли;	
	
КонецПроцедуры

Функция ВыгрузитьДанныеСсылочногоОбъекта(Значение, ИсходящиеДанные, ИмяПКО, ПКОСвойств, ТипПриемника, УзелСвойства, Знач ВыгрузитьТолькоСсылку)
	
	ЭтоПравилоСГлобальнойВыгрузкой = Ложь;
	УзелСсылки    = ВыгрузитьПоПравилу(Значение, , ИсходящиеДанные, , ИмяПКО, , ВыгрузитьТолькоСсылку, ПКОСвойств, ЭтоПравилоСГлобальнойВыгрузкой);
	ТипУзлаСсылки = ТипЗнч(УзелСсылки);

	Если ПустаяСтрока(ТипПриемника) Тогда
				
		ТипПриемника  = ПКОСвойств.Приемник;
		УстановитьАтрибут(УзелСвойства, "Тип", ТипПриемника);
				
	КонецЕсли;
			
	Если УзелСсылки = Неопределено Тогда
				
		Возврат Неопределено;
				
	КонецЕсли;
				
	ДобавитьСвойстваДляВыгрузки(УзелСсылки, ТипУзлаСсылки, УзелСвойства, ЭтоПравилоСГлобальнойВыгрузкой);	
	
	Возврат УзелСсылки;
	
КонецФункции

Функция ОпределитьТипДанныхДляПриемника(Значение)
	
	ТипПриемника = одТипЗначенияСтрокой(Значение);
	
	// Есть ли хоть какое ПКО с типом приемника ТипПриемника
	// если правила нет - то "", если есть , то то что нашли оставляем.
	СтрокаТаблицы = ТаблицаПравилКонвертации.Найти(ТипПриемника, "Приемник");
	
	Если СтрокаТаблицы = Неопределено Тогда
		ТипПриемника = "";
	КонецЕсли;
	
	Возврат ТипПриемника;
	
КонецФункции

Процедура ВыполнитьПриведениеЗначенияКДлине(Значение, ПКС)
	
	Значение = ПривестиНомерКДлине(Строка(Значение), ПКС.ПриводитьКДлине);
		
КонецПроцедуры

// Формирует узлы свойств объекта приемника в соответствии с указанной коллекцией правил конвертации свойств.
//
// Параметры:
//  Источник		     - Произвольный - произвольный источник данных.
//  Приемник		     - ЗаписьXML - xml-узел объекта приемника.
//  ВходящиеДанные	     - Произвольный - произвольные вспомогательные данные, передаваемые правилу
//                         для выполнения конвертации.
//  ИсходящиеДанные      - Произвольный - произвольные вспомогательные данные, передаваемые правилам
//                         конвертации объектов свойств.
//  ПКО				     - СтрокаТаблицыЗначений - ссылка на правило конвертации объектов.
//  КоллекцияПКС         - см. КоллекцияПравилаКонвертацииСвойств
//  УзелКоллекцииСвойств - ЗаписьXML - xml-узел коллекции свойств.
//  ОбъектКоллекции      - Произвольный - если указан, то выполняется выгрузка свойств объекта коллекции, иначе Источника.
//  ИмяПредопределенногоЭлемента - Строка - если указан, то в свойствах пишется имя предопределенного элемента.
//  ПКГС                 - ссылка на правило конвертации группы свойств (папка-родитель коллекции ПКС). 
//                         Например, табличная часть документа.
// 
Процедура ВыгрузитьСвойства(Источник, Приемник, ВходящиеДанные, ИсходящиеДанные, ПКО, КоллекцияПКС, УзелКоллекцииСвойств = Неопределено, 
	ОбъектКоллекции = Неопределено, ИмяПредопределенногоЭлемента = Неопределено, Знач ВыгрузитьТолькоСсылку = Ложь, 
	СписокВременныхФайлов = Неопределено)
	
	Перем КлючИЗначение, ВидСубконто, Субконто, ИмяПКОВидСубконто, УзелСубконто; // Пустышки, для корректного запуска
	                                                                             // обработчиков.
	
	Если УзелКоллекцииСвойств = Неопределено Тогда
		
		УзелКоллекцииСвойств = Приемник;
		
	КонецЕсли;
	
	// Выгружаем имя предопределенного если оно указано.
	Если ИмяПредопределенногоЭлемента <> Неопределено Тогда
		
		УзелКоллекцииСвойств.ЗаписатьНачалоЭлемента("Свойство");
		УстановитьАтрибут(УзелКоллекцииСвойств, "Имя", "{ИмяПредопределенногоЭлемента}");
		Если НЕ ВыполнитьОбменДаннымиВОптимизированномФормате Тогда
			УстановитьАтрибут(УзелКоллекцииСвойств, "Тип", "Строка");
		КонецЕсли;
		одЗаписатьЭлемент(УзелКоллекцииСвойств, "Значение", ИмяПредопределенногоЭлемента);
		УзелКоллекцииСвойств.ЗаписатьКонецЭлемента();		
		
	КонецЕсли;
		
	Для каждого ПКС Из КоллекцияПКС Цикл
		
		Если ПКС.УпрощеннаяВыгрузкаСвойства Тогда
						
			 //	Создаем узел свойства
			 
			УзелКоллекцииСвойств.ЗаписатьНачалоЭлемента("Свойство");
			УстановитьАтрибут(УзелКоллекцииСвойств, "Имя", ПКС.Приемник);
			
			Если НЕ ВыполнитьОбменДаннымиВОптимизированномФормате
				И Не ПустаяСтрока(ПКС.ТипПриемника) Тогда
			
				УстановитьАтрибут(УзелКоллекцииСвойств, "Тип", ПКС.ТипПриемника);
				
			КонецЕсли;
			
			Если ПКС.НеЗамещать Тогда
				
				УстановитьАтрибут(УзелКоллекцииСвойств, "НеЗамещать",	"true");
				
			КонецЕсли;
			
			Если ПКС.ПоискПоДатеНаРавенство  Тогда
				
				УстановитьАтрибут(УзелКоллекцииСвойств, "ПоискПоДатеНаРавенство", "true");
				
			КонецЕсли;
			
			Значение = Неопределено;
			ПолучитьЗначениеСвойства(Значение, ОбъектКоллекции, ПКО, ПКС, ВходящиеДанные, Источник);
			
			Если ПКС.ПриводитьКДлине <> 0 Тогда
				
				ВыполнитьПриведениеЗначенияКДлине(Значение, ПКС);
								
			КонецЕсли;
			
			ЭтоNULL = Ложь;
			Пусто = одПустое(Значение, ЭтоNULL);
						
			Если Пусто Тогда
				
				// Надо записать что это пустое значение.
				Если НЕ ВыполнитьОбменДаннымиВОптимизированномФормате Тогда
					одЗаписатьЭлемент(УзелКоллекцииСвойств, "Пусто");
				КонецЕсли;
				
				УзелКоллекцииСвойств.ЗаписатьКонецЭлемента();
				Продолжить;
				
			КонецЕсли;
			
			одЗаписатьЭлемент(УзелКоллекцииСвойств,	"Значение", Значение);
			
			УзелКоллекцииСвойств.ЗаписатьКонецЭлемента();
			Продолжить;	
			
		ИначеЕсли ПКС.ВидПриемника = "ВидыСубконтоСчета" Тогда
			
			ВыгрузитьСубконто(Источник, Приемник, ВходящиеДанные, ИсходящиеДанные, ПКО,
				ПКС, УзелКоллекцииСвойств, ОбъектКоллекции, ВыгрузитьТолькоСсылку);
			
			Продолжить;
			
		ИначеЕсли ПКС.Имя = "{УникальныйИдентификатор}" 
			И ПКС.Источник = "{УникальныйИдентификатор}" 
			И ПКС.Приемник = "{УникальныйИдентификатор}" Тогда
			
			Если Источник = Неопределено Тогда
				Продолжить;
			КонецЕсли;
			
			Если ЗначениеСсылочногоТипа(Источник) Тогда
				УникальныйИдентификатор = Источник.УникальныйИдентификатор();
			Иначе
				
				НачальноеЗначение = Новый УникальныйИдентификатор();
				СтруктураДляПроверкиНаличияСвойства = Новый Структура("Ссылка", НачальноеЗначение);
				ЗаполнитьЗначенияСвойств(СтруктураДляПроверкиНаличияСвойства, Источник);
				
				Если НачальноеЗначение <> СтруктураДляПроверкиНаличияСвойства.Ссылка
					И ЗначениеСсылочногоТипа(СтруктураДляПроверкиНаличияСвойства.Ссылка) Тогда
					УникальныйИдентификатор = Источник.Ссылка.УникальныйИдентификатор();
				КонецЕсли;
				
			КонецЕсли;
			
			УзелКоллекцииСвойств.ЗаписатьНачалоЭлемента("Свойство");
			УстановитьАтрибут(УзелКоллекцииСвойств, "Имя", "{УникальныйИдентификатор}");
			
			Если НЕ ВыполнитьОбменДаннымиВОптимизированномФормате Тогда 
				УстановитьАтрибут(УзелКоллекцииСвойств, "Тип", "Строка");
			КонецЕсли;
			
			одЗаписатьЭлемент(УзелКоллекцииСвойств, "Значение", УникальныйИдентификатор);
			УзелКоллекцииСвойств.ЗаписатьКонецЭлемента();
			Продолжить;
			
		ИначеЕсли ПКС.ЭтоГруппа Тогда
			
			ВыгрузитьГруппуСвойств(Источник, Приемник, ВходящиеДанные, ИсходящиеДанные, ПКО, ПКС, УзелКоллекцииСвойств, ВыгрузитьТолькоСсылку, СписокВременныхФайлов);
			Продолжить;
			
		КонецЕсли;

		
		//	Инициализируем значение, которое будем конвертировать.
		Значение 	 = Неопределено;
		ИмяПКО		 = ПКС.ПравилоКонвертации;
		НеЗамещать   = ПКС.НеЗамещать;
		
		Пусто		 = Ложь;
		Выражение	 = Неопределено;
		ТипПриемника = ПКС.ТипПриемника;

		ЭтоNULL      = Ложь;

		
		// Обработчик ПередВыгрузкой
		Если ПКС.ЕстьОбработчикПередВыгрузкой Тогда
			
			Отказ = Ложь;
			
			Попытка
				
				Если ФлагРежимОтладкиОбработчиков Тогда
					
					Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКС, "ПередВыгрузкой"));
					
				Иначе
					
					Выполнить(ПКС.ПередВыгрузкой);
					
				КонецЕсли;
				
			Исключение
				
				ЗаписатьИнформациюОбОшибкеОбработчикиПКС(55, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
					ПКО, ПКС, Источник, "ПередВыгрузкойСвойства", Значение);
				
			КонецПопытки;
			
			Если Отказ Тогда // Отказ от выгрузки свойства
				
				Продолжить;
				
			КонецЕсли;
			
		КонецЕсли;

        		
        //	Создаем узел свойства
		Если ПустаяСтрока(ПКС.ИмяПараметраДляПередачи) Тогда
			
			УзелСвойства = СоздатьУзел("Свойство");
			УстановитьАтрибут(УзелСвойства, "Имя", ПКС.Приемник);
			
		Иначе
			
			УзелСвойства = СоздатьУзел("ЗначениеПараметра");
			УстановитьАтрибут(УзелСвойства, "Имя", ПКС.ИмяПараметраДляПередачи);
			
		КонецЕсли;
		
		Если НеЗамещать Тогда
			
			УстановитьАтрибут(УзелСвойства, "НеЗамещать",	"true");
			
		КонецЕсли;
		
		Если ПКС.ПоискПоДатеНаРавенство  Тогда
			
			УстановитьАтрибут(УзелКоллекцииСвойств, "ПоискПоДатеНаРавенство", "true");
			
		КонецЕсли;

        		
		//	Возможно правило конвертации уже определено.
		Если Не ПустаяСтрока(ИмяПКО) Тогда
			
			ПКОСвойств = Правила[ИмяПКО];
			
		Иначе
			
			ПКОСвойств = Неопределено;
			
		КонецЕсли;


		//	Попытка определить тип свойства приемника.
		Если ПустаяСтрока(ТипПриемника)	И ПКОСвойств <> Неопределено Тогда
			
			ТипПриемника = ПКОСвойств.Приемник;
			УстановитьАтрибут(УзелСвойства, "Тип", ТипПриемника);
			
		ИначеЕсли НЕ ВыполнитьОбменДаннымиВОптимизированномФормате 
			И Не ПустаяСтрока(ТипПриемника) Тогда
			
			УстановитьАтрибут(УзелСвойства, "Тип", ТипПриемника);
						
		КонецЕсли;
		
		Если Не ПустаяСтрока(ИмяПКО)
			И ПКОСвойств <> Неопределено
			И ПКОСвойств.ЕстьОбработчикПоследовательностьПолейПоиска = Истина Тогда
			
			УстановитьАтрибут(УзелСвойства, "ИмяПКО", ИмяПКО);
			
		КонецЕсли;
		
        //	Определяем конвертируемое значение.
		Если Выражение <> Неопределено Тогда
			
			одЗаписатьЭлемент(УзелСвойства, "Выражение", Выражение);
			ДобавитьПодчиненный(УзелКоллекцииСвойств, УзелСвойства);
			Продолжить;
			
		ИначеЕсли Пусто Тогда
			
			Если ПустаяСтрока(ТипПриемника) Тогда
				
				Продолжить;
				
			КонецЕсли;
			
			Если НЕ ВыполнитьОбменДаннымиВОптимизированномФормате Тогда 
				одЗаписатьЭлемент(УзелСвойства, "Пусто");
			КонецЕсли;
			
			ДобавитьПодчиненный(УзелКоллекцииСвойств, УзелСвойства);
			Продолжить;
			
		Иначе
			
			ПолучитьЗначениеСвойства(Значение, ОбъектКоллекции, ПКО, ПКС, ВходящиеДанные, Источник);
			
			Если ПКС.ПриводитьКДлине <> 0 Тогда
				
				ВыполнитьПриведениеЗначенияКДлине(Значение, ПКС);
								
			КонецЕсли;
						
		КонецЕсли;


		СтароеЗначениеДоОбработчикаПриВыгрузке = Значение;
		Пусто = одПустое(Значение, ЭтоNULL);

		
		// Обработчик ПриВыгрузке
		Если ПКС.ЕстьОбработчикПриВыгрузке Тогда
			
			Отказ = Ложь;
			
			Попытка
				
				Если ФлагРежимОтладкиОбработчиков Тогда
					
					Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКС, "ПриВыгрузке"));
					
				Иначе
					
					Выполнить(ПКС.ПриВыгрузке);
					
				КонецЕсли;
				
			Исключение
				
				ЗаписатьИнформациюОбОшибкеОбработчикиПКС(56, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
					ПКО, ПКС, Источник, "ПриВыгрузкеСвойства", Значение);
				
			КонецПопытки;
				
			Если Отказ Тогда // Отказ от выгрузки свойства
				
				Продолжить;
				
			КонецЕсли;
			
		КонецЕсли;


		// Инициализируем еще раз переменную Пусто, может быть Значение было изменено 
		// в обработчике "При выгрузке".
		Если СтароеЗначениеДоОбработчикаПриВыгрузке <> Значение Тогда
			
			Пусто = одПустое(Значение, ЭтоNULL);
			
		КонецЕсли;

		Если Пусто Тогда
			
			Если ЭтоNULL 
				Или Значение = Неопределено Тогда
				
				Продолжить;
				
			КонецЕсли;
			
			Если ПустаяСтрока(ТипПриемника) Тогда
				
				ТипПриемника = ОпределитьТипДанныхДляПриемника(Значение);
				
				Если Не ПустаяСтрока(ТипПриемника) Тогда				
				
					УстановитьАтрибут(УзелСвойства, "Тип", ТипПриемника);
				
				КонецЕсли;
				
			КонецЕсли;			
				
			// Если тип множественный, то возможно это пустая ссылка и выгрузить ее нужно именно с указанием типа.
			Если НЕ ВыполнитьОбменДаннымиВОптимизированномФормате Тогда
				одЗаписатьЭлемент(УзелСвойства, "Пусто");
			КонецЕсли;
			
			ДобавитьПодчиненный(УзелКоллекцииСвойств, УзелСвойства);
			Продолжить;
			
		КонецЕсли;

      		
		УзелСсылки = Неопределено;
		
		Если (ПКОСвойств <> Неопределено) 
			Или (Не ПустаяСтрока(ИмяПКО)) Тогда
			
			УзелСсылки = ВыгрузитьДанныеСсылочногоОбъекта(Значение, ИсходящиеДанные, ИмяПКО, ПКОСвойств, ТипПриемника, УзелСвойства, ВыгрузитьТолькоСсылку);
			
			Если УзелСсылки = Неопределено Тогда
				Продолжить;				
			КонецЕсли;				
										
		Иначе
			
			СвойствоУстановлено = Ложь;
			ТипЗначения = ТипЗнч(Значение);
			ДобавитьЗначениеСвойстваВУзел(Значение, ТипЗначения, ТипПриемника, УзелСвойства, СвойствоУстановлено);
						
			Если НЕ СвойствоУстановлено Тогда
				
				МенеджерЗначения = Менеджеры(ТипЗначения);
				
				Если МенеджерЗначения = Неопределено Тогда
					Продолжить;
				КонецЕсли;
				
				ПКОСвойств = МенеджерЗначения.ПКО;
				
				Если ПКОСвойств = Неопределено Тогда
					Продолжить;
				КонецЕсли;
				
				ИмяПКО = ПКОСвойств.Имя;
				
				УзелСсылки = ВыгрузитьДанныеСсылочногоОбъекта(Значение, ИсходящиеДанные, ИмяПКО, ПКОСвойств, ТипПриемника, УзелСвойства, ВыгрузитьТолькоСсылку);
			
				Если УзелСсылки = Неопределено Тогда
					Продолжить;				
				КонецЕсли;				
												
			КонецЕсли;
			
		КонецЕсли;


		
		// Обработчик ПослеВыгрузки

		Если ПКС.ЕстьОбработчикПослеВыгрузки Тогда
			
			Отказ = Ложь;
			
			Попытка
				
				Если ФлагРежимОтладкиОбработчиков Тогда
					
					Выполнить(ПолучитьСтрокуВызоваОбработчика(ПКС, "ПослеВыгрузки"));
					
				Иначе
					
					Выполнить(ПКС.ПослеВыгрузки);
					
				КонецЕсли;
				
			Исключение
				
				ЗаписатьИнформациюОбОшибкеОбработчикиПКС(57, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
					ПКО, ПКС, Источник, "ПослеВыгрузкиСвойства", Значение);
				
			КонецПопытки;
				
			Если Отказ Тогда // Отказ от выгрузки свойства
				
				Продолжить;
				
			КонецЕсли;
			
		КонецЕсли;

		
		ДобавитьПодчиненный(УзелКоллекцииСвойств, УзелСвойства);
		
	КонецЦикла;		//	по ПКС

КонецПроцедуры

// Производит выгрузку объекта выборки в соответствии с указанным правилом.
//
// Параметры:
//  Объект         - выгружаемый объект выборки.
//  Правило        - ссылка на правило выгрузки данных.
//  Свойства       - свойства объекта метаданного выгружаемого объекта.
//  ВходящиеДанные - произвольные вспомогательные данные.
// 
Процедура ВыгрузкаОбъектаВыборки(Объект, Правило, Свойства=Неопределено, ВходящиеДанные=Неопределено, ВыборкаДляВыгрузкиДанных = Неопределено)

	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	Если ФлагКомментироватьОбработкуОбъектов Тогда
		
		ОписаниеТипов = Новый ОписаниеТипов("Строка");
		ОбъектСтрока  = ОписаниеТипов.ПривестиЗначение(Объект);
		Если Не ПустаяСтрока(ОбъектСтрока) Тогда
			ПрОбъекта   = ОбъектСтрока + "  (" + ТипЗнч(Объект) + ")";
		Иначе
			ПрОбъекта   = ТипЗнч(Объект);
		КонецЕсли;
		
		СтрокаСообщения = ПодставитьПараметрыВСтроку(НСтр("ru = 'Выгрузка объекта: %1'"), ПрОбъекта);
		ЗаписатьВПротоколВыполнения(СтрокаСообщения, , Ложь, 1, 7);
		
	КонецЕсли;
	
	ИмяПКО			= Правило.ПравилоКонвертации;
	Отказ			= Ложь;
	ИсходящиеДанные	= Неопределено;
	
	// Глобальный обработчик ПередВыгрузкойОбъекта.
	Если ЕстьГлобальныйОбработчикПередВыгрузкойОбъекта Тогда
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(Конвертация, "ПередВыгрузкойОбъекта"));
				
			Иначе
				
				Выполнить(Конвертация.ПередВыгрузкойОбъекта);
				
			КонецЕсли;
			
		Исключение
			
			ИмяОбработчика = НСтр("ru = '%1 (глобальный)'");
			ЗаписатьИнформациюОбОшибкеОбработчикиПВД(65, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), 
				Правило.Имя,
				ПодставитьПараметрыВСтроку(ИмяОбработчика, "ПередВыгрузкойОбъектаВыборки"),
				Объект);
			
		КонецПопытки;
			
		Если Отказ Тогда
			Возврат;
		КонецЕсли;
		
	КонецЕсли;
	
	// Обработчик ПередВыгрузкой
	Если Не ПустаяСтрока(Правило.ПередВыгрузкой) Тогда
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(Правило, "ПередВыгрузкой"));
				
			Иначе
				
				Выполнить(Правило.ПередВыгрузкой);
				
			КонецЕсли;
			
		Исключение
			ЗаписатьИнформациюОбОшибкеОбработчикиПВД(33, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				Правило.Имя, "ПередВыгрузкойОбъектаВыборки", Объект);
		КонецПопытки;
		
		Если Отказ Тогда
			Возврат;
		КонецЕсли;
		
	КонецЕсли;
	
	УзелСсылки = Неопределено;
	
	ВыгрузитьПоПравилу(Объект, , ИсходящиеДанные, , ИмяПКО, УзелСсылки, , , , ВыборкаДляВыгрузкиДанных);
	
	// Глобальный обработчик ПослеВыгрузкиОбъекта.
	Если ЕстьГлобальныйОбработчикПослеВыгрузкиОбъекта Тогда
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(Конвертация, "ПослеВыгрузкиОбъекта"));
				
			Иначе
				
				Выполнить(Конвертация.ПослеВыгрузкиОбъекта);
			
			КонецЕсли;
			
		Исключение
			
			ИмяОбработчика = НСтр("ru = '%1 (глобальный)'");
			ЗаписатьИнформациюОбОшибкеОбработчикиПВД(69, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				Правило.Имя, 
				ПодставитьПараметрыВСтроку(ИмяОбработчика, "ПослеВыгрузкиОбъектаВыборки"), 
				Объект);
			
		КонецПопытки;
		
	КонецЕсли;
	
	// Обработчик ПослеВыгрузки
	Если Не ПустаяСтрока(Правило.ПослеВыгрузки) Тогда
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(Правило, "ПослеВыгрузки"));
				
			Иначе
				
				Выполнить(Правило.ПослеВыгрузки);
				
			КонецЕсли;
			
		Исключение
			ЗаписатьИнформациюОбОшибкеОбработчикиПВД(34, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), 
				Правило.Имя, "ПослеВыгрузкиОбъектаВыборки", Объект);
		КонецПопытки;
		
	КонецЕсли;
	
КонецПроцедуры

// Параметры:
//   МетаданныеОбъекта - ОбъектМетаданных
//
Функция ПолучитьИмяПервогоРеквизитаМетаданных(МетаданныеОбъекта)
	
	НаборРеквизитов = МетаданныеОбъекта.Реквизиты; // КоллекцияОбъектовМетаданных
	
	Если НаборРеквизитов.Количество() = 0 Тогда
		Возврат "";
	КонецЕсли;
	
	Возврат НаборРеквизитов.Получить(0).Имя;
	
КонецФункции

Функция ПолучитьВыборкуДляВыгрузкиСОграничениями(Правило, ВыборкаДляПодстановкиВПКО = Неопределено, Свойства = Неопределено)
	
	ИмяМетаданных           = Правило.ИмяОбъектаДляЗапроса;
	
	СтрокаРазрешения = ?(ВыгружатьТолькоРазрешенные, " РАЗРЕШЕННЫЕ ", ""); // @Query-part-1
	
	ЭтоВыгрузкаРегистра = (Правило.ИмяОбъектаДляЗапроса = Неопределено);
	
	Если ЭтоВыгрузкаРегистра Тогда
		
		ИтоговоеОграничениеПоДате = ПолучитьСтрокуОграниченияПоДатеДляЗапроса(Свойства, Свойства.ИмяТипа, Правило.ИмяОбъектаДляЗапросаРегистра, Ложь);
		
		ТекстЗапроса = 
		"ВЫБРАТЬ РАЗРЕШЕННЫЕ
		| *
		|
		| ,NULL КАК Активность
		| ,NULL КАК Регистратор
		| ,NULL КАК НомерСтроки
		| ,NULL КАК Период
		|
		|ИЗ &ИмяТаблицыМетаданных КАК ОбъектДляВыгрузки";
		
		Если Свойства.ПодчиненныйРегистратору Тогда
			
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ",NULL КАК Активность", "");
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ",NULL КАК Регистратор", "");
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ",NULL КАК НомерСтроки", "");
			
		КонецЕсли;
		
		Если Свойства.Периодический Тогда
			
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, ",NULL КАК Период", "");
			
		КонецЕсли;
		
		Если ПустаяСтрока(СтрокаРазрешения) Тогда
			
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ВЫБРАТЬ РАЗРЕШЕННЫЕ", "ВЫБРАТЬ");
			
		КонецЕсли;
				
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяТаблицыМетаданных", Правило.ИмяОбъектаДляЗапросаРегистра);
		ТекстЗапроса = ТекстЗапроса + Символы.ПС + ИтоговоеОграничениеПоДате;
		
		ПостроительОтчета.Текст = ТекстЗапроса;
		ПостроительОтчета.ЗаполнитьНастройки();
		
	Иначе
		
		ИтоговоеОграничениеПоДате = ПолучитьСтрокуОграниченияПоДатеДляЗапроса(Свойства, Свойства.ИмяТипа,, Ложь);
		
		ТекстЗапроса = 
		"ВЫБРАТЬ РАЗРЕШЕННЫЕ
		| *
		|
		| ИЗ &ИмяТаблицыМетаданных КАК ОбъектДляВыгрузки";
		
		Если ПустаяСтрока(СтрокаРазрешения) Тогда
			
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ВЫБРАТЬ РАЗРЕШЕННЫЕ", "ВЫБРАТЬ");
			
		КонецЕсли;
		
		Если Правило.ВыбиратьДанныеДляВыгрузкиОднимЗапросом <> Истина Тогда
			
			ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "*", "ОбъектДляВыгрузки.Ссылка КАК Ссылка");
			
		КонецЕсли;
		
		ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяТаблицыМетаданных", ИмяМетаданных);
		ТекстЗапроса = ТекстЗапроса + Символы.ПС + ИтоговоеОграничениеПоДате;
		
		ПсевдонимКомпоновщикаОтчета = СтрЗаменить(ИмяМетаданных, ".", "_");
		СтрокаУсловияКомпоновщика = "{ГДЕ Ссылка.* КАК ПсевдонимКомпоновщикаОтчета}";
		СтрокаУсловияКомпоновщика = СтрЗаменить(СтрокаУсловияКомпоновщика, "ПсевдонимКомпоновщикаОтчета", ПсевдонимКомпоновщикаОтчета);
		ТекстЗапроса = ТекстЗапроса + Символы.ПС + СтрокаУсловияКомпоновщика;
		
		ПостроительОтчета.Текст = ТекстЗапроса;
		
	КонецЕсли;
	
	ПостроительОтчета.Отбор.Сбросить();
	Если Правило.НастройкиПостроителя <> Неопределено Тогда
		ПостроительОтчета.УстановитьНастройки(Правило.НастройкиПостроителя);
	КонецЕсли;
	
	ПостроительОтчета.Параметры.Вставить("ДатаНачала", ДатаНачала);
	ПостроительОтчета.Параметры.Вставить("ДатаОкончания", ДатаОкончания);

	ПостроительОтчета.Выполнить();
	Выборка = ПостроительОтчета.Результат.Выбрать();
	
	Если Правило.ВыбиратьДанныеДляВыгрузкиОднимЗапросом Тогда
		ВыборкаДляПодстановкиВПКО = Выборка;
	КонецЕсли;
		
	Возврат Выборка;
		
КонецФункции

Функция ПолучитьВыборкуДляВыгрузкиПоПроизвольномуАлгоритму(ВыборкаДанных)
	
	Выборка = Неопределено;
	
	Если ТипЗнч(ВыборкаДанных) = Тип("ВыборкаИзРезультатаЗапроса") Тогда
		
		Выборка = ВыборкаДанных;
		
	ИначеЕсли ТипЗнч(ВыборкаДанных) = Тип("РезультатЗапроса") Тогда
		
		Выборка = ВыборкаДанных.Выбрать();
		
	ИначеЕсли ТипЗнч(ВыборкаДанных) = Тип("Запрос") Тогда
		
		РезультатЗапроса = ВыборкаДанных.Выполнить();
		Выборка          = РезультатЗапроса.Выбрать();
		
	КонецЕсли;
		
	Возврат Выборка;	
	
КонецФункции

Функция ПолучитьСтрокуНабораКонстантДляВыгрузки(ТаблицаДанныхКонстантДляВыгрузки)
	
	СтрокаНабораКонстант = "";
	
	Для Каждого СтрокаТаблицы Из ТаблицаДанныхКонстантДляВыгрузки Цикл
		
		Если Не ПустаяСтрока(СтрокаТаблицы.Источник) Тогда
		
			СтрокаНабораКонстант = СтрокаНабораКонстант + ", " + СтрокаТаблицы.Источник;
			
		КонецЕсли;
		
	КонецЦикла;	
	
	Если Не ПустаяСтрока(СтрокаНабораКонстант) Тогда
		
		СтрокаНабораКонстант = Сред(СтрокаНабораКонстант, 3);
		
	КонецЕсли;
	
	Возврат СтрокаНабораКонстант;
	
КонецФункции

Процедура ВыгрузитьНаборКонстант(Правило, Свойства, ИсходящиеДанные)
	
	Если Свойства.ПКО <> Неопределено Тогда
	
		СтрокаИменНабораКонстант = ПолучитьСтрокуНабораКонстантДляВыгрузки(Свойства.ПКО.Свойства);
		
	Иначе
		
		СтрокаИменНабораКонстант = "";
		
	КонецЕсли;
			
	НаборКонстант = Константы.СоздатьНабор(СтрокаИменНабораКонстант);
	НаборКонстант.Прочитать();
	ВыгрузкаОбъектаВыборки(НаборКонстант, Правило, Свойства, ИсходящиеДанные);	
	
КонецПроцедуры

Функция ОпределитьНужноВыбиратьВсеПоля(Правило)
	
	НужныВсеПоляДляВыборки = НЕ ПустаяСтрока(Конвертация.ПередВыгрузкойОбъекта)
		ИЛИ НЕ ПустаяСтрока(Правило.ПередВыгрузкой)
		ИЛИ НЕ ПустаяСтрока(Конвертация.ПослеВыгрузкиОбъекта)
		ИЛИ НЕ ПустаяСтрока(Правило.ПослеВыгрузки);		
		
	Возврат НужныВсеПоляДляВыборки;	
	
КонецФункции

// Выгружает данные по указанному правилу.
//
// Параметры:
//  Правило        - ссылка на правило выгрузки данных.
// 
Процедура ВыгрузитьДанныеПоПравилу(Правило)
	
	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	ИмяПКО = Правило.ПравилоКонвертации;
	
	Если Не ПустаяСтрока(ИмяПКО) Тогда
		
		ПКО = Правила[ИмяПКО];
		
	КонецЕсли;
	
	Если ФлагКомментироватьОбработкуОбъектов Тогда
		
		СтрокаСообщения = ПодставитьПараметрыВСтроку(НСтр("ru = 'Правило выгрузки данных: %1 (%2)'"), СокрЛП(Правило.Имя), СокрЛП(Правило.Наименование));
		ЗаписатьВПротоколВыполнения(СтрокаСообщения, , Ложь, , 4);
		
	КонецЕсли;
	
	// Обработчик ПередОбработкой
	Отказ			= Ложь;
	ИсходящиеДанные	= Неопределено;
	ВыборкаДанных	= Неопределено;
	
	Если Не ПустаяСтрока(Правило.ПередОбработкой) Тогда
	
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(Правило, "ПередОбработкой"));
				
			Иначе
				
				Выполнить(Правило.ПередОбработкой);
				
			КонецЕсли;
			
		Исключение
			
			ЗаписатьИнформациюОбОшибкеОбработчикиПВД(31, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				Правило.Имя, "ПередОбработкойВыгрузкиДанных");
			
		КонецПопытки;
		
		Если Отказ Тогда
			
			Возврат;
			
		КонецЕсли;
		
	КонецЕсли;
	
	// Стандартная выборка с отбором.
	Если Правило.СпособОтбораДанных = "СтандартнаяВыборка" И Правило.ИспользоватьОтбор Тогда
		
		Свойства	= Менеджеры[Правило.ОбъектВыборки];
		ИмяТипа		= Свойства.ИмяТипа;
		
		ВыборкаДляПКО = Неопределено;
		Выборка = ПолучитьВыборкуДляВыгрузкиСОграничениями(Правило, ВыборкаДляПКО, Свойства);
		
		ЭтоНеСсылочныйТип = ИмяТипа =  "РегистрСведений" Или ИмяТипа = "РегистрБухгалтерии";
		
		Пока Выборка.Следующий() Цикл
			
			Если ЭтоНеСсылочныйТип Тогда
				ВыгрузкаОбъектаВыборки(Выборка, Правило, Свойства, ИсходящиеДанные);
			Иначе					
				ВыгрузкаОбъектаВыборки(Выборка.Ссылка, Правило, Свойства, ИсходящиеДанные, ВыборкаДляПКО);
			КонецЕсли;
			
		КонецЦикла;
		
	// Стандартная выборка без отбора.
	ИначеЕсли (Правило.СпособОтбораДанных = "СтандартнаяВыборка") Тогда
		
		Свойства	= Менеджеры(Правило.ОбъектВыборки);
		ИмяТипа		= Свойства.ИмяТипа;
		
		Если ИмяТипа = "Константы" Тогда
			
			ВыгрузитьНаборКонстант(Правило, Свойства, ИсходящиеДанные);
			
		Иначе
			
			ЭтоНеСсылочныйТип = ИмяТипа =  "РегистрСведений" 
				ИЛИ ИмяТипа = "РегистрБухгалтерии";
			
			Если ЭтоНеСсылочныйТип Тогда
					
				ВыбиратьВсеПоля = ОпределитьНужноВыбиратьВсеПоля(Правило);
				
			Иначе
				
				// получаем только ссылку
				ВыбиратьВсеПоля = Правило.ВыбиратьДанныеДляВыгрузкиОднимЗапросом;	
				
			КонецЕсли;
			
			Выборка = ПолучитьВыборкуДляВыгрузкиОчисткиДанных(Свойства, ИмяТипа, , , ВыбиратьВсеПоля);
			ВыборкаДляПКО = ?(Правило.ВыбиратьДанныеДляВыгрузкиОднимЗапросом, Выборка, Неопределено);
			
			Если Выборка = Неопределено Тогда
				Возврат;
			КонецЕсли;
			
			Пока Выборка.Следующий() Цикл
				
				Если ЭтоНеСсылочныйТип Тогда
					
					ВыгрузкаОбъектаВыборки(Выборка, Правило, Свойства, ИсходящиеДанные);
					
				Иначе
					
					ВыгрузкаОбъектаВыборки(Выборка.Ссылка, Правило, Свойства, ИсходящиеДанные, ВыборкаДляПКО);
					
				КонецЕсли;
				
			КонецЦикла;
			
		КонецЕсли;
		
	ИначеЕсли Правило.СпособОтбораДанных = "ПроизвольныйАлгоритм" Тогда

		Если ВыборкаДанных <> Неопределено Тогда
			
			Выборка = ПолучитьВыборкуДляВыгрузкиПоПроизвольномуАлгоритму(ВыборкаДанных);
			
			Если Выборка <> Неопределено Тогда
				
				Пока Выборка.Следующий() Цикл
					
					ВыгрузкаОбъектаВыборки(Выборка, Правило, , ИсходящиеДанные);
					
				КонецЦикла;
				
			Иначе
				
				Для каждого Объект Из ВыборкаДанных Цикл
					
					ВыгрузкаОбъектаВыборки(Объект, Правило, , ИсходящиеДанные);
					
				КонецЦикла;
				
			КонецЕсли;
			
		КонецЕсли;
			
	КонецЕсли;

	
	// Обработчик ПослеОбработки

	Если Не ПустаяСтрока(Правило.ПослеОбработки) Тогда
	
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(Правило, "ПослеОбработки"));
				
			Иначе
				
				Выполнить(Правило.ПослеОбработки);
				
			КонецЕсли;
			
		Исключение
			
			ЗаписатьИнформациюОбОшибкеОбработчикиПВД(32, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
				Правило.Имя, "ПослеОбработкиВыгрузкиДанных");
			
		КонецПопытки;
		
	 КонецЕсли;	
	
КонецПроцедуры

// Обходит дерево правил выгрузки данных и выполняет выгрузку.
//
// Параметры:
//  Строки         - коллекция строк дерева значений.
// 
Процедура ОбработатьПравилаВыгрузки(Строки, СоответствиеУзловПланаОбменаИСтрокВыгрузки)
	
	Для каждого ПравилоВыгрузки Из Строки Цикл
		
		Если ПравилоВыгрузки.Включить = 0 Тогда
			
			Продолжить;
			
		КонецЕсли; 
		
		Если (ПравилоВыгрузки.СсылкаНаУзелОбмена <> Неопределено 
				И НЕ ПравилоВыгрузки.СсылкаНаУзелОбмена.Пустая()) Тогда
			
			МассивПравилВыгрузки = СоответствиеУзловПланаОбменаИСтрокВыгрузки.Получить(ПравилоВыгрузки.СсылкаНаУзелОбмена);
			
			Если МассивПравилВыгрузки = Неопределено Тогда
				
				МассивПравилВыгрузки = Новый Массив();	
				
			КонецЕсли;
			
			МассивПравилВыгрузки.Добавить(ПравилоВыгрузки);
			
			СоответствиеУзловПланаОбменаИСтрокВыгрузки.Вставить(ПравилоВыгрузки.СсылкаНаУзелОбмена, МассивПравилВыгрузки);
			
			Продолжить;
			
		КонецЕсли;

		Если ПравилоВыгрузки.ЭтоГруппа Тогда
			
			ОбработатьПравилаВыгрузки(ПравилоВыгрузки.Строки, СоответствиеУзловПланаОбменаИСтрокВыгрузки);
			Продолжить;
			
		КонецЕсли;
		
		ВыгрузитьДанныеПоПравилу(ПравилоВыгрузки);
		
	КонецЦикла; 
	
КонецПроцедуры

Функция СкопироватьМассивПравилВыгрузки(ИсходныйМассив)
	
	РезультирующийМассив = Новый Массив();
	
	Для Каждого Элемент Из ИсходныйМассив Цикл
		
		РезультирующийМассив.Добавить(Элемент);	
		
	КонецЦикла;
	
	Возврат РезультирующийМассив;
	
КонецФункции

// Возвращаемое значение:
//   СтрокаДереваЗначений - строка дерева правил выгрузки данных:
//     * Имя - Строка
//     * Наименование - Строка
//
Функция НайтиСтрокуДереваПравилВыгрузкиПоТипуВыгрузки(МассивСтрок, ТипВыгрузки)
	
	Для Каждого СтрокаМассива Из МассивСтрок Цикл
		
		Если СтрокаМассива.ОбъектВыборки = ТипВыгрузки Тогда
			
			Возврат СтрокаМассива;
			
		КонецЕсли;
			
	КонецЦикла;
	
	Возврат Неопределено;
	
КонецФункции

Процедура УдалитьСтрокуДереваПравилВыгрузкиПоТипуВыгрузкиИзМассива(МассивСтрок, ЭлементУдаления)
	
	Счетчик = МассивСтрок.Количество() - 1;
	Пока Счетчик >= 0 Цикл
		
		СтрокаМассива = МассивСтрок[Счетчик];
		
		Если СтрокаМассива = ЭлементУдаления Тогда
			
			МассивСтрок.Удалить(Счетчик);
			Возврат;
			
		КонецЕсли; 
		
		Счетчик = Счетчик - 1;	
		
	КонецЦикла;
	
КонецПроцедуры

// Параметры:
//   Данные - ЛюбаяСсылка - ссылка справочника, документа, ключ регистра сведений и т.д.
//
Процедура ПолучитьСтрокуПравилВыгрузкиПоОбъектуОбмена(Данные, МетаданныеПоследнегоОбъекта, МетаданныеОбъектаВыгрузки, 
	ПоследняяСтрокаПравилВыгрузки, ТекущаяСтрокаПравилаВыгрузки, ВременныйМассивПравилКонвертации, ОбъектДляПравилВыгрузки, 
	ВыгружаетсяРегистр, ВыгружаютсяКонстанты, КонстантыБылиВыгружены)
	
	ТекущаяСтрокаПравилаВыгрузки = Неопределено;
	ОбъектДляПравилВыгрузки = Неопределено;
	ВыгружаетсяРегистр = Ложь;
	ВыгружаютсяКонстанты = Ложь;
	
	Если МетаданныеПоследнегоОбъекта = МетаданныеОбъектаВыгрузки
		И ПоследняяСтрокаПравилВыгрузки = Неопределено Тогда
		
		Возврат;
		
	КонецЕсли;
	
	СтруктураДанных = МенеджерыДляПлановОбмена[МетаданныеОбъектаВыгрузки];
	
	Если СтруктураДанных = Неопределено Тогда
		
		ВыгружаютсяКонстанты = Метаданные.Константы.Содержит(МетаданныеОбъектаВыгрузки);
		
		Если КонстантыБылиВыгружены 
			ИЛИ НЕ ВыгружаютсяКонстанты Тогда
			
			Возврат;
			
		КонецЕсли;
		
		// Нужно найти правило для констант.
		Если МетаданныеПоследнегоОбъекта <> МетаданныеОбъектаВыгрузки Тогда
		
			ТекущаяСтрокаПравилаВыгрузки = НайтиСтрокуДереваПравилВыгрузкиПоТипуВыгрузки(ВременныйМассивПравилКонвертации, Тип("КонстантыНабор"));
			
		Иначе
			
			ТекущаяСтрокаПравилаВыгрузки = ПоследняяСтрокаПравилВыгрузки;
			
		КонецЕсли;
		
		Возврат;
		
	КонецЕсли;
	
	Если СтруктураДанных.ЭтоСсылочныйТип = Истина Тогда
		
		Если МетаданныеПоследнегоОбъекта <> МетаданныеОбъектаВыгрузки Тогда
		
			ТекущаяСтрокаПравилаВыгрузки = НайтиСтрокуДереваПравилВыгрузкиПоТипуВыгрузки(ВременныйМассивПравилКонвертации, СтруктураДанных.ТипСсылки);
			
		Иначе
			
			ТекущаяСтрокаПравилаВыгрузки = ПоследняяСтрокаПравилВыгрузки;
			
		КонецЕсли;
		
		ОбъектДляПравилВыгрузки = Данные.Ссылка;
		
	ИначеЕсли СтруктураДанных.ЭтоРегистр = Истина Тогда
		
		Если МетаданныеПоследнегоОбъекта <> МетаданныеОбъектаВыгрузки Тогда
		
			ТекущаяСтрокаПравилаВыгрузки = НайтиСтрокуДереваПравилВыгрузкиПоТипуВыгрузки(ВременныйМассивПравилКонвертации, СтруктураДанных.ТипСсылки);
			
		Иначе
			
			ТекущаяСтрокаПравилаВыгрузки = ПоследняяСтрокаПравилВыгрузки;	
			
		КонецЕсли;
		
		ОбъектДляПравилВыгрузки = Данные;
		
		ВыгружаетсяРегистр = Истина;
		
	КонецЕсли;
	
КонецПроцедуры

Функция ВыполнитьВыгрузкуИзмененныхДанныхДляУзлаОбмена(УзелОбмена, МассивПравилКонвертации, СтруктураДляУдаленияРегистрацииИзменений)
	
	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	СтруктураДляУдаленияРегистрацииИзменений.Вставить("МассивПКО", Неопределено);
	СтруктураДляУдаленияРегистрацииИзменений.Вставить("НомерСообщения", Неопределено);
	
	ЗаписьXML = Новый ЗаписьXML();
	ЗаписьXML.УстановитьСтроку();
	
	// Создаем новое сообщение
	ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
		
	ЗаписьСообщения.НачатьЗапись(ЗаписьXML, УзелОбмена);
	
	// Считаем количество записанных объектов.
	КоличествоНайденныхДляЗаписиОбъектов = 0;
	
	ПоследнийОбъектМетаданных = Неопределено;
	ПоследняяСтрокаПравилаВыгрузки = Неопределено; // см. НайтиСтрокуДереваПравилВыгрузкиПоТипуВыгрузки
	
	ТекущийОбъектМетаданных = Неопределено;
	ТекущаяСтрокаПравилаВыгрузки = Неопределено; // см. НайтиСтрокуДереваПравилВыгрузкиПоТипуВыгрузки
	
	ИсходящиеДанные = Неопределено;
	
	ВременныйМассивПравилКонвертации = СкопироватьМассивПравилВыгрузки(МассивПравилКонвертации);
	
	Отказ           = Ложь;
	ИсходящиеДанные = Неопределено;
	ВыборкаДанных   = Неопределено;
	
	ОбъектДляПравилВыгрузки = Неопределено;
	КонстантыБылиВыгружены = Ложь;
	// начинаем транзакцию
	Если ИспользоватьТранзакцииПриВыгрузкеДляПлановОбмена Тогда
		НачатьТранзакцию();
	КонецЕсли;
	
	Попытка
	
		// Получаем выборку измененных данных.
		МассивВыгружаемыхМетаданных = Новый Массив();
		
		// Дополняем массив только теми метаданными по которым есть правила выгрузки - остальные метаданные нас не интересуют.
		Для Каждого СтрокаПравилаВыгрузки Из ВременныйМассивПравилКонвертации Цикл
			
			МетаданныеПВД = Метаданные.НайтиПоТипу(СтрокаПравилаВыгрузки.ОбъектВыборки);
			МассивВыгружаемыхМетаданных.Добавить(МетаданныеПВД);
			
		КонецЦикла;
		
		ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(ЗаписьСообщения.Получатель, ЗаписьСообщения.НомерСообщения, МассивВыгружаемыхМетаданных);
		
		СтруктураДляУдаленияРегистрацииИзменений.НомерСообщения = ЗаписьСообщения.НомерСообщения;
		
		Пока ВыборкаИзменений.Следующий() Цикл
					
			Данные = ВыборкаИзменений.Получить();
			КоличествоНайденныхДляЗаписиОбъектов = КоличествоНайденныхДляЗаписиОбъектов + 1;
			
			ТипДанныхДляВыгрузки = ТипЗнч(Данные); 
			
			Удаление = (ТипДанныхДляВыгрузки = одТипУдалениеОбъекта);
			
			// удаление не отрабатываем
			Если Удаление Тогда
				Продолжить;
			КонецЕсли;
			
			ТекущийОбъектМетаданных = Данные.Метаданные();
			
			// Работа с данными полученными из узла обмена
			// по данным определяем правило конвертации и производим выгрузку данных.
			
			ВыгружаетсяРегистр = Ложь;
			ВыгружаютсяКонстанты = Ложь;
			
			ПолучитьСтрокуПравилВыгрузкиПоОбъектуОбмена(Данные, ПоследнийОбъектМетаданных, ТекущийОбъектМетаданных,
				ПоследняяСтрокаПравилаВыгрузки, ТекущаяСтрокаПравилаВыгрузки, ВременныйМассивПравилКонвертации, ОбъектДляПравилВыгрузки,
				ВыгружаетсяРегистр, ВыгружаютсяКонстанты, КонстантыБылиВыгружены);
				
			Если ПоследнийОбъектМетаданных <> ТекущийОбъектМетаданных Тогда
				
				// после обработки
				Если ПоследняяСтрокаПравилаВыгрузки <> Неопределено Тогда
			
					Если Не ПустаяСтрока(ПоследняяСтрокаПравилаВыгрузки.ПослеОбработки) Тогда
					
						Попытка
							
							Если ФлагРежимОтладкиОбработчиков Тогда
								
								Выполнить(ПолучитьСтрокуВызоваОбработчика(ПоследняяСтрокаПравилаВыгрузки, "ПослеОбработки"));
								
							Иначе
								
								Выполнить(ПоследняяСтрокаПравилаВыгрузки.ПослеОбработки);
								
							КонецЕсли;
							
						Исключение
							
							ЗаписатьИнформациюОбОшибкеОбработчикиПВД(32, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
								ПоследняяСтрокаПравилаВыгрузки.Имя, "ПослеОбработкиВыгрузкиДанных");
							
						КонецПопытки;
						
					КонецЕсли;
					
				КонецЕсли;
				
				// перед обработкой
				Если ТекущаяСтрокаПравилаВыгрузки <> Неопределено Тогда
					
					Если ФлагКомментироватьОбработкуОбъектов Тогда
						
						СтрокаСообщения = ПодставитьПараметрыВСтроку(НСтр("ru = 'Правило выгрузки данных: %1 (%2)'"),
							СокрЛП(ТекущаяСтрокаПравилаВыгрузки.Имя), СокрЛП(ТекущаяСтрокаПравилаВыгрузки.Наименование));
						ЗаписатьВПротоколВыполнения(СтрокаСообщения, , Ложь, , 4);
						
					КонецЕсли;
					
					// Обработчик ПередОбработкой
					Отказ			= Ложь;
					ИсходящиеДанные	= Неопределено;
					ВыборкаДанных	= Неопределено;
					
					Если Не ПустаяСтрока(ТекущаяСтрокаПравилаВыгрузки.ПередОбработкой) Тогда
					
						Попытка
							
							Если ФлагРежимОтладкиОбработчиков Тогда
								
								Выполнить(ПолучитьСтрокуВызоваОбработчика(ТекущаяСтрокаПравилаВыгрузки, "ПередОбработкой"));
								
							Иначе
								
								Выполнить(ТекущаяСтрокаПравилаВыгрузки.ПередОбработкой);
								
							КонецЕсли;
							
						Исключение
							
							ЗаписатьИнформациюОбОшибкеОбработчикиПВД(31, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
								ТекущаяСтрокаПравилаВыгрузки.Имя, "ПередОбработкойВыгрузкиДанных");
							
						КонецПопытки;
						
					КонецЕсли;
					
					Если Отказ Тогда
						
						// Удаляем правило из массива правил.
						ТекущаяСтрокаПравилаВыгрузки = Неопределено;
						УдалитьСтрокуДереваПравилВыгрузкиПоТипуВыгрузкиИзМассива(ВременныйМассивПравилКонвертации, ТекущаяСтрокаПравилаВыгрузки);
						ОбъектДляПравилВыгрузки = Неопределено;
						
					КонецЕсли;
					
				КонецЕсли;
				
			КонецЕсли;
			
			// Есть правило по которому нужно делать выгрузку данных.
			Если ТекущаяСтрокаПравилаВыгрузки <> Неопределено Тогда
				
				Если ВыгружаетсяРегистр Тогда
					
					Для Каждого СтрокаРегистра Из ОбъектДляПравилВыгрузки Цикл
						ВыгрузкаОбъектаВыборки(СтрокаРегистра, ТекущаяСтрокаПравилаВыгрузки, , ИсходящиеДанные);
					КонецЦикла;
					
				ИначеЕсли ВыгружаютсяКонстанты Тогда
					
					Свойства	= Менеджеры[ТекущаяСтрокаПравилаВыгрузки.ОбъектВыборки];
					ВыгрузитьНаборКонстант(ТекущаяСтрокаПравилаВыгрузки, Свойства, ИсходящиеДанные);
					
				Иначе
				
					ВыгрузкаОбъектаВыборки(ОбъектДляПравилВыгрузки, ТекущаяСтрокаПравилаВыгрузки, , ИсходящиеДанные);
				
				КонецЕсли;
				
			КонецЕсли;
			
			ПоследнийОбъектМетаданных = ТекущийОбъектМетаданных;
			ПоследняяСтрокаПравилаВыгрузки = ТекущаяСтрокаПравилаВыгрузки; 
			
			Если КоличествоОбработанныхОбъектовДляОбновленияСтатуса > 0 
				И КоличествоНайденныхДляЗаписиОбъектов % КоличествоОбработанныхОбъектовДляОбновленияСтатуса = 0 Тогда
				
				Попытка
					ИмяМетаданных = ТекущийОбъектМетаданных.ПолноеИмя();
				Исключение
					ИмяМетаданных = "";
				КонецПопытки;
				
			КонецЕсли;
			
			Если ИспользоватьТранзакцииПриВыгрузкеДляПлановОбмена 
				И (КоличествоЭлементовВТранзакцииПриВыгрузкеДляПлановОбмена > 0)
				И (КоличествоНайденныхДляЗаписиОбъектов = КоличествоЭлементовВТранзакцииПриВыгрузкеДляПлановОбмена) Тогда
				
				// Промежуточную транзакцию закрываем и открываем новую.
				ЗафиксироватьТранзакцию();
				НачатьТранзакцию();
				
				КоличествоНайденныхДляЗаписиОбъектов = 0;
			КонецЕсли;
			
		КонецЦикла;
		
		// Завершаем запись сообщения
		ЗаписьСообщения.ЗакончитьЗапись();
		
		ЗаписьXML.Закрыть();
		
		Если ИспользоватьТранзакцииПриВыгрузкеДляПлановОбмена Тогда
			ЗафиксироватьТранзакцию();
		КонецЕсли;
		
	Исключение
		
		Если ИспользоватьТранзакцииПриВыгрузкеДляПлановОбмена Тогда
			ОтменитьТранзакцию();
		КонецЕсли;
		
		ЗП = ПолучитьСтруктуруЗаписиПротокола(72, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		ЗП.УзелПланаОбмена  = УзелОбмена;
		ЗП.Объект = Данные;
		ЗП.ТипОбъекта = ТипДанныхДляВыгрузки;
		
		ЗаписатьВПротоколВыполнения(72, ЗП, Истина);
						
		ЗаписьXML.Закрыть();
		
		Возврат Ложь;
		
	КонецПопытки;
	
	// событие после обработки
	Если ПоследняяСтрокаПравилаВыгрузки <> Неопределено Тогда
	
		Если Не ПустаяСтрока(ПоследняяСтрокаПравилаВыгрузки.ПослеОбработки) Тогда
		
			Попытка
				
				Если ФлагРежимОтладкиОбработчиков Тогда
					
					Выполнить(ПолучитьСтрокуВызоваОбработчика(ПоследняяСтрокаПравилаВыгрузки, "ПослеОбработки"));
					
				Иначе
					
					Выполнить(ПоследняяСтрокаПравилаВыгрузки.ПослеОбработки);
					
				КонецЕсли;
				
			Исключение
				ЗаписатьИнформациюОбОшибкеОбработчикиПВД(32, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()),
					ПоследняяСтрокаПравилаВыгрузки.Имя, "ПослеОбработкиВыгрузкиДанных");
				
			КонецПопытки;
			
		КонецЕсли;
		
	КонецЕсли;
	
	СтруктураДляУдаленияРегистрацииИзменений.МассивПКО = ВременныйМассивПравилКонвертации;
	
	Возврат Не Отказ;
	
КонецФункции

Функция ОбработатьВыгрузкуДляПлановОбмена(СоответствиеУзловИПравилВыгрузки, СтруктураДляУдаленияРегистрацииИзменений)
	
	УдачнаяВыгрузка = Истина;
	
	Для Каждого СтрокаСоответствия Из СоответствиеУзловИПравилВыгрузки Цикл
		
		УзелОбмена = СтрокаСоответствия.Ключ;
		МассивПравилКонвертации = СтрокаСоответствия.Значение;
		
		ЛокальнаяСтруктураДляУдаленияРегистрацииИзменений = Новый Структура();
		
		ТекущаяУдачнаяВыгрузка = ВыполнитьВыгрузкуИзмененныхДанныхДляУзлаОбмена(УзелОбмена, МассивПравилКонвертации, ЛокальнаяСтруктураДляУдаленияРегистрацииИзменений);
		
		УдачнаяВыгрузка = УдачнаяВыгрузка И ТекущаяУдачнаяВыгрузка;
		
		Если ЛокальнаяСтруктураДляУдаленияРегистрацииИзменений.МассивПКО <> Неопределено
			И ЛокальнаяСтруктураДляУдаленияРегистрацииИзменений.МассивПКО.Количество() > 0 Тогда
			
			СтруктураДляУдаленияРегистрацииИзменений.Вставить(УзелОбмена, ЛокальнаяСтруктураДляУдаленияРегистрацииИзменений);	
			
		КонецЕсли;
		
	КонецЦикла;
	
	Возврат УдачнаяВыгрузка;
	
КонецФункции

Процедура ОбработатьИзменениеРегистрацииДляУзловОбмена(СоответствиеУзловИПравилВыгрузки)
	
	Для Каждого Элемент Из СоответствиеУзловИПравилВыгрузки Цикл
	
		Если ТипУдаленияРегистрацииИзмененийДляУзловОбменаПослеВыгрузки = 0 Тогда
			
			Возврат;
			
		ИначеЕсли ТипУдаленияРегистрацииИзмененийДляУзловОбменаПослеВыгрузки = 1 Тогда
			
			// Для всех изменений которые были в плане обмена отменяем регистрацию.
			ПланыОбмена.УдалитьРегистрациюИзменений(Элемент.Ключ, Элемент.Значение.НомерСообщения);
			
		ИначеЕсли ТипУдаленияРегистрацииИзмененийДляУзловОбменаПослеВыгрузки = 2 Тогда	
			
			// Удаление изменений только для метаданных выгруженных объектов первого уровня.
			
			Для Каждого ВыгруженноеПКО Из Элемент.Значение.МассивПКО Цикл
				
				Правило = Правила[ВыгруженноеПКО.ПравилоКонвертации]; // см. НайтиПравило
				
				Если ЗначениеЗаполнено(Правило.Источник) Тогда
					
					Менеджер = Менеджеры[Правило.Источник];
					
					ПланыОбмена.УдалитьРегистрациюИзменений(Элемент.Ключ, Менеджер.ОбъектМД);
					
				КонецЕсли;
				
			КонецЦикла;
			
		КонецЕсли;
	
	КонецЦикла;
	
КонецПроцедуры

#КонецОбласти

#Область ЭкспортируемыеПроцедурыИФункции

// Открывает файл обмена, читает атрибуты корневого узла файла в соответствии с форматом обмена.
//
// Параметры:
//  ТолькоПрочитатьШапку - Булево - если Истина, то после прочтения шапки файла обмена
//  (корневой узел), файл закрывается.
//
Процедура ОткрытьФайлЗагрузки(ТолькоПрочитатьШапку=Ложь, ДанныеФайлаОбмена = "") Экспорт

	Если ПустаяСтрока(ИмяФайлаОбмена) И ТолькоПрочитатьШапку Тогда
		ДатаНачала         = "";
		ДатаОкончания      = "";
		ДатаВыгрузкиДанных = "";
		ВерсияПравилОбмена = "";
		Комментарий        = "";
		Возврат;
	КонецЕсли;


	ИмяФайлаЗагрузкиДанных = ИмяФайлаОбмена;
		
	// Архивные файлы будем идентифицировать по расширению ".zip".
	Если СтрНайти(ИмяФайлаОбмена, ".zip") > 0 Тогда
		
		ИмяФайлаЗагрузкиДанных = РаспаковатьZipФайл(ИмяФайлаОбмена);		 
		
	КонецЕсли; 
	
	
	ФлагОшибки = Ложь;
	ФайлОбмена = Новый ЧтениеXML();

	Попытка
		Если НЕ ПустаяСтрока(ДанныеФайлаОбмена) Тогда
			ФайлОбмена.УстановитьСтроку(ДанныеФайлаОбмена);
		Иначе
			ФайлОбмена.ОткрытьФайл(ИмяФайлаЗагрузкиДанных);
		КонецЕсли;
	Исключение
		ЗаписатьВПротоколВыполнения(5);
		Возврат;
	КонецПопытки;
	
	ФайлОбмена.Прочитать();


	мАтрибутыФайлаОбмена = Новый Структура;
	
	
	Если ФайлОбмена.ЛокальноеИмя = "ФайлОбмена" Тогда
		
		мАтрибутыФайлаОбмена.Вставить("ВерсияФормата",            одАтрибут(ФайлОбмена, одТипСтрока, "ВерсияФормата"));
		мАтрибутыФайлаОбмена.Вставить("ДатаВыгрузки",             одАтрибут(ФайлОбмена, одТипДата,   "ДатаВыгрузки"));
		мАтрибутыФайлаОбмена.Вставить("НачалоПериодаВыгрузки",    одАтрибут(ФайлОбмена, одТипДата,   "НачалоПериодаВыгрузки"));
		мАтрибутыФайлаОбмена.Вставить("ОкончаниеПериодаВыгрузки", одАтрибут(ФайлОбмена, одТипДата,   "ОкончаниеПериодаВыгрузки"));
		мАтрибутыФайлаОбмена.Вставить("ИмяКонфигурацииИсточника", одАтрибут(ФайлОбмена, одТипСтрока, "ИмяКонфигурацииИсточника"));
		мАтрибутыФайлаОбмена.Вставить("ИмяКонфигурацииПриемника", одАтрибут(ФайлОбмена, одТипСтрока, "ИмяКонфигурацииПриемника"));
		мАтрибутыФайлаОбмена.Вставить("ИдПравилКонвертации",      одАтрибут(ФайлОбмена, одТипСтрока, "ИдПравилКонвертации"));
		
		ДатаНачала         = мАтрибутыФайлаОбмена.НачалоПериодаВыгрузки;
		ДатаОкончания      = мАтрибутыФайлаОбмена.ОкончаниеПериодаВыгрузки;
		ДатаВыгрузкиДанных = мАтрибутыФайлаОбмена.ДатаВыгрузки;
		Комментарий        = одАтрибут(ФайлОбмена, одТипСтрока, "Комментарий");
		
	Иначе
		
		ЗаписатьВПротоколВыполнения(9);
		Возврат;
		
	КонецЕсли;


	ФайлОбмена.Прочитать();
			
	ИмяУзла = ФайлОбмена.ЛокальноеИмя;
		
	Если ИмяУзла = "ПравилаОбмена" Тогда
		Если БезопаснаяЗагрузка И ЗначениеЗаполнено(ИмяФайлаПравилОбмена) Тогда
			ЗагрузитьПравилаОбмена(ИмяФайлаПравилОбмена, "XMLФайл");
			ФайлОбмена.Пропустить();
		Иначе
			ЗагрузитьПравилаОбмена(ФайлОбмена, "ЧтениеXML");
		КонецЕсли;				
	Иначе
		ФайлОбмена.Закрыть();
		ФайлОбмена = Новый ЧтениеXML();
		Попытка
			
			Если НЕ ПустаяСтрока(ДанныеФайлаОбмена) Тогда
				ФайлОбмена.УстановитьСтроку(ДанныеФайлаОбмена);
			Иначе
				ФайлОбмена.ОткрытьФайл(ИмяФайлаЗагрузкиДанных);
			КонецЕсли;
			
		Исключение
			
			ЗаписатьВПротоколВыполнения(5);
			Возврат;
			
		КонецПопытки;
		
		ФайлОбмена.Прочитать();
		
	КонецЕсли; 
	
	мБылиПрочитаныПравилаОбменаПриЗагрузке = Истина;

	Если ТолькоПрочитатьШапку Тогда
		
		ФайлОбмена.Закрыть();
		Возврат;
		
	КонецЕсли;
   
КонецПроцедуры

Процедура ОбновитьПометкиВсехРодителейУПравилВыгрузки(СтрокиДереваПравилВыгрузки, НужноУстанавливатьПометки = Истина)
	
	Если СтрокиДереваПравилВыгрузки.Строки.Количество() = 0 Тогда
		
		Если НужноУстанавливатьПометки Тогда
			УстановитьПометкиРодителей(СтрокиДереваПравилВыгрузки, "Включить");	
		КонецЕсли;
		
	Иначе
		
		НужныПометки = Истина;
		
		Для Каждого СтрокаДереваПравил Из СтрокиДереваПравилВыгрузки.Строки Цикл
			
			ОбновитьПометкиВсехРодителейУПравилВыгрузки(СтрокаДереваПравил, НужныПометки);
			Если НужныПометки = Истина Тогда
				НужныПометки = Ложь;
			КонецЕсли;
			
		КонецЦикла;
		
	КонецЕсли;
	
КонецПроцедуры

Процедура ЗаполнитьСвойстваДляПоиска(СтруктураДанных, ПКС)
	
	Для Каждого СтрокаПолей Из ПКС Цикл
		
		Если СтрокаПолей.ЭтоГруппа Тогда
						
			Если СтрокаПолей.ВидПриемника = "ТабличнаяЧасть" 
				ИЛИ СтрНайти(СтрокаПолей.ВидПриемника, "НаборДвижений") > 0 Тогда
				
				ИмяСтруктурыПриемника = СтрокаПолей.Приемник + ?(СтрокаПолей.ВидПриемника = "ТабличнаяЧасть", "ТабличнаяЧасть", "НаборЗаписей");
				
				ВнутренняяСтруктура = СтруктураДанных[ИмяСтруктурыПриемника];
				
				Если ВнутренняяСтруктура = Неопределено Тогда
					ВнутренняяСтруктура = Новый Соответствие();
				КонецЕсли;
				
				СтруктураДанных[ИмяСтруктурыПриемника] = ВнутренняяСтруктура;
				
			Иначе
				
				ВнутренняяСтруктура = СтруктураДанных;	
				
			КонецЕсли;
			
			ЗаполнитьСвойстваДляПоиска(ВнутренняяСтруктура, СтрокаПолей.ПравилаГруппы);
									
		Иначе
			
			Если ПустаяСтрока(СтрокаПолей.ТипПриемника)	Тогда
				
				Продолжить;
				
			КонецЕсли;
			
			СтруктураДанных[СтрокаПолей.Приемник] = СтрокаПолей.ТипПриемника;
			
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

Процедура УдалитьЛишниеЭлементыИзСоответствия(СтруктураДанных)
	
	Для Каждого Элемент Из СтруктураДанных Цикл
		
		Если ТипЗнч(Элемент.Значение) = одТипСоответствие Тогда
			
			УдалитьЛишниеЭлементыИзСоответствия(Элемент.Значение);
			
			Если Элемент.Значение.Количество() = 0 Тогда
				СтруктураДанных.Удалить(Элемент.Ключ);
			КонецЕсли;
			
		КонецЕсли;		
		
	КонецЦикла;		
	
КонецПроцедуры

Процедура ЗаполнитьИнформациюПоТипамДанныхПриемника(СтруктураДанных, Правила)
	
	Для Каждого Строка Из Правила Цикл
		
		Если ПустаяСтрока(Строка.Приемник) Тогда
			Продолжить;
		КонецЕсли;
		
		ДанныеСтруктуры = СтруктураДанных[Строка.Приемник];
		Если ДанныеСтруктуры = Неопределено Тогда
			
			ДанныеСтруктуры = Новый Соответствие();
			СтруктураДанных[Строка.Приемник] = ДанныеСтруктуры;
			
		КонецЕсли;
		
		// Обходим поля поиска и ПКС и запоминаем типы данных.
		ЗаполнитьСвойстваДляПоиска(ДанныеСтруктуры, Строка.СвойстваПоиска);
				
		// Свойства
		ЗаполнитьСвойстваДляПоиска(ДанныеСтруктуры, Строка.Свойства);
		
	КонецЦикла;
	
	УдалитьЛишниеЭлементыИзСоответствия(СтруктураДанных);	
	
КонецПроцедуры

Процедура СоздатьСтрокуСТипамиСвойств(ЗаписьXML, ТипыСвойств)
	
	Если ТипЗнч(ТипыСвойств.Значение) = одТипСоответствие Тогда
		
		Если ТипыСвойств.Значение.Количество() = 0 Тогда
			Возврат;
		КонецЕсли;
		
		ЗаписьXML.ЗаписатьНачалоЭлемента(ТипыСвойств.Ключ);
		
		Для Каждого Элемент Из ТипыСвойств.Значение Цикл
			СоздатьСтрокуСТипамиСвойств(ЗаписьXML, Элемент);
		КонецЦикла;
		
		ЗаписьXML.ЗаписатьКонецЭлемента();
		
	Иначе		
		
		одЗаписатьЭлемент(ЗаписьXML, ТипыСвойств.Ключ, ТипыСвойств.Значение);
		
	КонецЕсли;
	
КонецПроцедуры

Функция СоздатьСтрокуСТипамиДляПриемника(СтруктураДанных)
	
	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.УстановитьСтроку();
	ЗаписьXML.ЗаписатьНачалоЭлемента("ИнформацияОТипахДанных");	
	
	Для Каждого Строка Из СтруктураДанных Цикл
		
		ЗаписьXML.ЗаписатьНачалоЭлемента("ТипДанных");
		УстановитьАтрибут(ЗаписьXML, "Имя", Строка.Ключ);
		
		Для Каждого СтрокаПодчинения Из Строка.Значение Цикл
			
			СоздатьСтрокуСТипамиСвойств(ЗаписьXML, СтрокаПодчинения);	
			
		КонецЦикла;
		
		ЗаписьXML.ЗаписатьКонецЭлемента();
		
	КонецЦикла;	
	
	ЗаписьXML.ЗаписатьКонецЭлемента();
	
	СтрокаРезультата = ЗаписьXML.Закрыть();
	Возврат СтрокаРезультата;
	
КонецФункции

Процедура ЗагрузитьОдинТипДанных(ПравилаОбмена, СоответствиеТипа, ИмяЛокальногоЭлемента)
	
	ИмяУзла = ИмяЛокальногоЭлемента;
	
	ПравилаОбмена.Прочитать();
	
	Если (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
		
		ПравилаОбмена.Прочитать();
		Возврат;
		
	ИначеЕсли ПравилаОбмена.ТипУзла = одТипУзлаXML_НачалоЭлемента Тогда
			
		// это новый элемент
		НовоеСоответствие = Новый Соответствие;
		СоответствиеТипа.Вставить(ИмяУзла, НовоеСоответствие);
		
		ЗагрузитьОдинТипДанных(ПравилаОбмена, НовоеСоответствие, ПравилаОбмена.ЛокальноеИмя);			
		ПравилаОбмена.Прочитать();
		
	Иначе
		СоответствиеТипа.Вставить(ИмяУзла, Тип(ПравилаОбмена.Значение));
		ПравилаОбмена.Прочитать();
	КонецЕсли;	
	
	ЗагрузитьСоответствиеТиповДляОдногоТипа(ПравилаОбмена, СоответствиеТипа);
	
КонецПроцедуры

Процедура ЗагрузитьСоответствиеТиповДляОдногоТипа(ПравилаОбмена, СоответствиеТипа)
	
	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		Если (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			
		    Прервать;
			
		КонецЕсли;
		
		// прочитали начало элемента
		ПравилаОбмена.Прочитать();
		
		Если ПравилаОбмена.ТипУзла = одТипУзлаXML_НачалоЭлемента Тогда
			
			// это новый элемент
			НовоеСоответствие = Новый Соответствие;
			СоответствиеТипа.Вставить(ИмяУзла, НовоеСоответствие);
			
			ЗагрузитьОдинТипДанных(ПравилаОбмена, НовоеСоответствие, ПравилаОбмена.ЛокальноеИмя);			
			
		Иначе
			СоответствиеТипа.Вставить(ИмяУзла, Тип(ПравилаОбмена.Значение));
			ПравилаОбмена.Прочитать();
		КонецЕсли;	
		
	КонецЦикла;	
	
КонецПроцедуры

Процедура ЗагрузитьИнформациюОТипахДанных()
	
	Пока ФайлОбмена.Прочитать() Цикл
		
		ИмяУзла = ФайлОбмена.ЛокальноеИмя;
		
		Если ИмяУзла = "ТипДанных" Тогда
			
			ИмяТипа = одАтрибут(ФайлОбмена, одТипСтрока, "Имя");
			
			СоответствиеТипа = Новый Соответствие;
			мСоответствиеТиповДанныхДляЗагрузки.Вставить(Тип(ИмяТипа), СоответствиеТипа);

			ЗагрузитьСоответствиеТиповДляОдногоТипа(ФайлОбмена, СоответствиеТипа);	
			
		ИначеЕсли (ИмяУзла = "ИнформацияОТипахДанных") И (ФайлОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
			
			Прервать;
			
		КонецЕсли;
		
	КонецЦикла;	
	
КонецПроцедуры

Процедура ЗагрузитьЗначенияПараметровОбменаДанными()
	
	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	Имя = одАтрибут(ФайлОбмена, одТипСтрока, "Имя");
		
	ТипСвойства = ПолучитьТипСвойстваПоДополнительнымДанным(Неопределено, Имя);
	
	Значение = ПрочитатьСвойство(ТипСвойства);
	
	Параметры.Вставить(Имя, Значение);	
	
	АлгоритмПослеЗагрузкиПараметра = "";
	Если СобытияПослеЗагрузкиПараметров.Свойство(Имя, АлгоритмПослеЗагрузкиПараметра)
		И Не ПустаяСтрока(АлгоритмПослеЗагрузкиПараметра) Тогда
		
		Если ФлагРежимОтладкиОбработчиков Тогда
			
			ВызватьИсключение НСтр("ru = 'Отладка обработчика ""После загрузки параметра"" не поддерживается.'");
			
		Иначе
			
			Выполнить(АлгоритмПослеЗагрузкиПараметра);
			
		КонецЕсли;
		
	КонецЕсли;
		
КонецПроцедуры

Функция ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена)
	
	ТекстОбработчика = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
	
	Если СтрНайти(ТекстОбработчика, Символы.ПС) = 0 Тогда
		Возврат ТекстОбработчика;
	КонецЕсли;
	
	ТекстОбработчика = СтрЗаменить(ТекстОбработчика, Символ(10), Символы.ПС);
	
	Возврат ТекстОбработчика;
	
КонецФункции

// Осуществляет загрузку правил обмена в соответствии с форматом.
//
// Параметры:
//  Источник        - Строка - объект, из которого осуществляется загрузка правил обмена;
//  ТипИсточника    - Строка - указывающая тип источника: "XMLФайл", "ЧтениеXML", "Строка".
// 
Процедура ЗагрузитьПравилаОбмена(Источник="", ТипИсточника="XMLФайл") Экспорт
	
	ИнициализироватьМенеджерыИСообщения();
	
	ЕстьГлобальныйОбработчикПередВыгрузкойОбъекта    = Ложь;
	ЕстьГлобальныйОбработчикПослеВыгрузкиОбъекта     = Ложь;
	
	ЕстьГлобальныйОбработчикПередКонвертациейОбъекта = Ложь;

	ЕстьГлобальныйОбработчикПередЗагрузкойОбъекта    = Ложь;
	ЕстьГлобальныйОбработчикПослеЗагрузкиОбъекта     = Ложь;
	
	СоздатьСтруктуруКонвертации();
	
	мТаблицаПравилКонвертацииСвойств = Новый ТаблицаЗначений;
	ИнициализацияТаблицыПравилКонвертацииСвойств(мТаблицаПравилКонвертацииСвойств);
	ДополнитьСлужебныеТаблицыКолонками();
	
	// Возможно выбраны встроенные правила обмена (один из макетов).
	
	ИмяВременногоФайлаПравилОбмена = "";
	Если ПустаяСтрока(Источник) Тогда
		
		Источник = ИмяФайлаПравилОбмена;
		Если мСписокМакетовПравилОбмена.НайтиПоЗначению(Источник) <> Неопределено Тогда
			Для каждого Макет Из Метаданные().Макеты Цикл
				Если Макет.Синоним = Источник Тогда
					Источник = Макет.Имя;
					Прервать;
				КонецЕсли; 
			КонецЦикла; 
			МакетПравилОбмена              = ПолучитьМакет(Источник);
			ИмяВременногоФайлаПравилОбмена = ПолучитьИмяВременногоФайла("xml");
			МакетПравилОбмена.Записать(ИмяВременногоФайлаПравилОбмена);
			Источник = ИмяВременногоФайлаПравилОбмена;
		КонецЕсли;
		
	КонецЕсли;

	
	Если ТипИсточника="XMLФайл" Тогда
		
		Если ПустаяСтрока(Источник) Тогда
			ЗаписатьВПротоколВыполнения(12);
			Возврат; 
		КонецЕсли;
		
		Файл = Новый Файл(Источник);
		Если Не Файл.Существует() Тогда
			ЗаписатьВПротоколВыполнения(3);
			Возврат; 
		КонецЕсли;
		
		ФайлПравилЗапакован = (Файл.Расширение = ".zip");
		
		Если ФайлПравилЗапакован Тогда
			
			// распаковка файла правил
			Источник = РаспаковатьZipФайл(Источник);
			
		КонецЕсли;
		
		ПравилаОбмена = Новый ЧтениеXML();
		ПравилаОбмена.ОткрытьФайл(Источник);
		ПравилаОбмена.Прочитать();
		
	ИначеЕсли ТипИсточника="Строка" Тогда
		
		ПравилаОбмена = Новый ЧтениеXML();
		ПравилаОбмена.УстановитьСтроку(Источник);
		ПравилаОбмена.Прочитать();
		
	ИначеЕсли ТипИсточника="ЧтениеXML" Тогда
		
		ПравилаОбмена = Источник;
		
	КонецЕсли; 
	

	Если Не ((ПравилаОбмена.ЛокальноеИмя = "ПравилаОбмена") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_НачалоЭлемента)) Тогда
		ЗаписатьВПротоколВыполнения(6);
		Возврат;
	КонецЕсли;


	ЗаписьXML = Новый ЗаписьXML;
	ЗаписьXML.УстановитьСтроку();
	ЗаписьXML.Отступ = Истина;
	ЗаписьXML.ЗаписатьНачалоЭлемента("ПравилаОбмена");
	

	Пока ПравилаОбмена.Прочитать() Цикл
		
		ИмяУзла = ПравилаОбмена.ЛокальноеИмя;
		
		// Реквизиты конвертации
		Если ИмяУзла = "ВерсияФормата" Тогда
			Значение = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			Конвертация.Вставить("ВерсияФормата", Значение);
			одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
		ИначеЕсли ИмяУзла = "Ид" Тогда
			Значение = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			Конвертация.Вставить("Ид",                   Значение);
			одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
		ИначеЕсли ИмяУзла = "Наименование" Тогда
			Значение = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			Конвертация.Вставить("Наименование",         Значение);
			одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
		ИначеЕсли ИмяУзла = "ДатаВремяСоздания" Тогда
			Значение = одЗначениеЭлемента(ПравилаОбмена, одТипДата);
			Конвертация.Вставить("ДатаВремяСоздания",    Значение);
			одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
			ВерсияПравилОбмена = Конвертация.ДатаВремяСоздания;
		ИначеЕсли ИмяУзла = "Источник" Тогда
			Значение = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			Конвертация.Вставить("Источник",             Значение);
			одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
		ИначеЕсли ИмяУзла = "Приемник" Тогда
			
			ВерсияПлатформыПриемника = ПравилаОбмена.ПолучитьАтрибут ("ВерсияПлатформы");
			ПлатформаПриемника = ОпределитьПоВерсииПлатформыПриемникаПлатформу(ВерсияПлатформыПриемника);
			
			Значение = одЗначениеЭлемента(ПравилаОбмена, одТипСтрока);
			Конвертация.Вставить("Приемник",             Значение);
			одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
			
		ИначеЕсли ИмяУзла = "УдалятьСопоставленныеОбъектыВПриемникеПриИхУдаленииВИсточнике" Тогда
			одПропустить(ПравилаОбмена);
		
		ИначеЕсли ИмяУзла = "Комментарий" Тогда
			одПропустить(ПравилаОбмена);
			
		ИначеЕсли ИмяУзла = "ОсновнойПланОбмена" Тогда
			одПропустить(ПравилаОбмена);

		ИначеЕсли ИмяУзла = "Параметры" Тогда
			ЗагрузитьПараметры(ПравилаОбмена, ЗаписьXML)

		// События конвертации
		
		ИначеЕсли ИмяУзла = "" Тогда
			
		ИначеЕсли ИмяУзла = "ПослеЗагрузкиПравилОбмена" Тогда
			Если РежимОбмена = "Загрузка" Тогда
				ПравилаОбмена.Пропустить();
			Иначе
				Конвертация.Вставить("ПослеЗагрузкиПравилОбмена", ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена));
			КонецЕсли;
		ИначеЕсли ИмяУзла = "ПередВыгрузкойДанных" Тогда
			Конвертация.Вставить("ПередВыгрузкойДанных", ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена));
			
		ИначеЕсли ИмяУзла = "ПослеВыгрузкиДанных" Тогда
			Конвертация.Вставить("ПослеВыгрузкиДанных",  ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена));

		ИначеЕсли ИмяУзла = "ПередВыгрузкойОбъекта" Тогда
			Конвертация.Вставить("ПередВыгрузкойОбъекта", ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена));
			ЕстьГлобальныйОбработчикПередВыгрузкойОбъекта = Не ПустаяСтрока(Конвертация.ПередВыгрузкойОбъекта);

		ИначеЕсли ИмяУзла = "ПослеВыгрузкиОбъекта" Тогда
			Конвертация.Вставить("ПослеВыгрузкиОбъекта", ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена));
			ЕстьГлобальныйОбработчикПослеВыгрузкиОбъекта = Не ПустаяСтрока(Конвертация.ПослеВыгрузкиОбъекта);

		ИначеЕсли ИмяУзла = "ПередЗагрузкойОбъекта" Тогда
			
			Значение = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			
			Если РежимОбмена = "Загрузка" Тогда
				
				Конвертация.Вставить("ПередЗагрузкойОбъекта", Значение);
				ЕстьГлобальныйОбработчикПередЗагрузкойОбъекта = Не ПустаяСтрока(Значение);
				
			Иначе
				
				одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
				
			КонецЕсли;
			
		ИначеЕсли ИмяУзла = "ПослеЗагрузкиОбъекта" Тогда
			
			Значение = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			
			Если РежимОбмена = "Загрузка" Тогда
				
				Конвертация.Вставить("ПослеЗагрузкиОбъекта", Значение);
				ЕстьГлобальныйОбработчикПослеЗагрузкиОбъекта = Не ПустаяСтрока(Значение);
				
			Иначе
				
				одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
				
			КонецЕсли;
			
		ИначеЕсли ИмяУзла = "ПередКонвертациейОбъекта" Тогда
			Конвертация.Вставить("ПередКонвертациейОбъекта", ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена));
			ЕстьГлобальныйОбработчикПередКонвертациейОбъекта = Не ПустаяСтрока(Конвертация.ПередКонвертациейОбъекта);
			
		ИначеЕсли ИмяУзла = "ПередЗагрузкойДанных" Тогда
			
			Значение = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			
			Если РежимОбмена = "Загрузка" Тогда
				
				Конвертация.ПередЗагрузкойДанных = Значение;
				
			Иначе
				
				одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
				
			КонецЕсли;
			
		ИначеЕсли ИмяУзла = "ПослеЗагрузкиДанных" Тогда
			
			Значение = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			
			Если РежимОбмена = "Загрузка" Тогда
				
				Конвертация.ПослеЗагрузкиДанных = Значение;
				
			Иначе
				
				одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
				
			КонецЕсли;
			
		ИначеЕсли ИмяУзла = "ПослеЗагрузкиПараметров" Тогда
			Конвертация.Вставить("ПослеЗагрузкиПараметров", ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена));
			
		ИначеЕсли ИмяУзла = "ПередОтправкойИнформацииОбУдалении" Тогда
			Конвертация.Вставить("ПередОтправкойИнформацииОбУдалении",  одЗначениеЭлемента(ПравилаОбмена, одТипСтрока));
			
		ИначеЕсли ИмяУзла = "ПередПолучениемИзмененныхОбъектов" Тогда
			Конвертация.Вставить("ПередПолучениемИзмененныхОбъектов", одЗначениеЭлемента(ПравилаОбмена, одТипСтрока));
			
		ИначеЕсли ИмяУзла = "ПриПолученииИнформацииОбУдалении" Тогда
			
			Значение = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			
			Если РежимОбмена = "Загрузка" Тогда
				
				Конвертация.Вставить("ПриПолученииИнформацииОбУдалении", Значение);
				
			Иначе
				
				одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
				
			КонецЕсли;
			
		ИначеЕсли ИмяУзла = "ПослеПолученияИнформацииОбУзлахОбмена" Тогда
			
			Значение = ПолучитьИзТекстаЗначениеОбработчика(ПравилаОбмена);
			
			Если РежимОбмена = "Загрузка" Тогда
				
				Конвертация.Вставить("ПослеПолученияИнформацииОбУзлахОбмена", Значение);
				
			Иначе
				
				одЗаписатьЭлемент(ЗаписьXML, ИмяУзла, Значение);
				
			КонецЕсли;

		// Правила
		
		ИначеЕсли ИмяУзла = "ПравилаВыгрузкиДанных" Тогда
		
 			Если РежимОбмена = "Загрузка" Тогда
				одПропустить(ПравилаОбмена);
			Иначе
				ЗагрузитьПравилаВыгрузки(ПравилаОбмена);
 			КонецЕсли; 
			
		ИначеЕсли ИмяУзла = "ПравилаКонвертацииОбъектов" Тогда
			ЗагрузитьПравилаКонвертации(ПравилаОбмена, ЗаписьXML);
			
		ИначеЕсли ИмяУзла = "ПравилаОчисткиДанных" Тогда
			ЗагрузитьПравилаОчистки(ПравилаОбмена, ЗаписьXML)
			
		ИначеЕсли ИмяУзла = "ПравилаРегистрацииОбъектов" Тогда
			одПропустить(ПравилаОбмена); // Правила регистрации объектов загружаем другой обработкой.
			
		// Алгоритмы, Запросы, Обработки.
		
		ИначеЕсли ИмяУзла = "Алгоритмы" Тогда
			ЗагрузитьАлгоритмы(ПравилаОбмена, ЗаписьXML);
			
		ИначеЕсли ИмяУзла = "Запросы" Тогда
			ЗагрузитьЗапросы(ПравилаОбмена, ЗаписьXML);

		ИначеЕсли ИмяУзла = "Обработки" Тогда
			ЗагрузитьОбработки(ПравилаОбмена, ЗаписьXML);
			
		// Выход
		ИначеЕсли (ИмяУзла = "ПравилаОбмена") И (ПравилаОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
		
			Если РежимОбмена <> "Загрузка" Тогда
				ПравилаОбмена.Закрыть();
			КонецЕсли;
			Прервать;

			
		// Ошибка формата
		Иначе
		    СтруктураЗаписи = Новый Структура("ИмяУзла", ИмяУзла);
			ЗаписатьВПротоколВыполнения(7, СтруктураЗаписи);
			Возврат;
		КонецЕсли;
	КонецЦикла;


	ЗаписьXML.ЗаписатьКонецЭлемента();
	мXMLПравила = ЗаписьXML.Закрыть();
	
	Для Каждого СтрокаПравилВыгрузки Из ТаблицаПравилВыгрузки.Строки Цикл
		ОбновитьПометкиВсехРодителейУПравилВыгрузки(СтрокаПравилВыгрузки, Истина);
	КонецЦикла;
	
	// Удаляем временный файл правил.
	Если Не ПустаяСтрока(ИмяВременногоФайлаПравилОбмена) Тогда
		Попытка
 			УдалитьФайлы(ИмяВременногоФайлаПравилОбмена);
		Исключение 
			ЗаписьЖурналаРегистрации(НСтр("ru = 'Универсальный обмен данными в формате XML'", КодОсновногоЯзыка()),
				УровеньЖурналаРегистрации.Ошибка,,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		КонецПопытки;
	КонецЕсли;
	
	Если ТипИсточника="XMLФайл"
		И ФайлПравилЗапакован Тогда
		
		Попытка
			УдалитьФайлы(Источник);
		Исключение 
			ЗаписьЖурналаРегистрации(НСтр("ru = 'Универсальный обмен данными в формате XML'", КодОсновногоЯзыка()),
				УровеньЖурналаРегистрации.Ошибка,,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		КонецПопытки;
		
	КонецЕсли;
	
	// Дополнительно нужна информация по типам данных приемника для быстрой загрузки данных.
	СтруктураДанных = Новый Соответствие();
	ЗаполнитьИнформациюПоТипамДанныхПриемника(СтруктураДанных, ТаблицаПравилКонвертации);
	
	мСтрокаТиповДляПриемника = СоздатьСтрокуСТипамиДляПриемника(СтруктураДанных);
	
	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	// Нужно вызвать событие после загрузки правил обмена.
	ТекстСобытияПослеЗагрузкиПравилОбмена = "";
	Если Конвертация.Свойство("ПослеЗагрузкиПравилОбмена", ТекстСобытияПослеЗагрузкиПравилОбмена)
		И Не ПустаяСтрока(ТекстСобытияПослеЗагрузкиПравилОбмена) Тогда
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				ВызватьИсключение НСтр("ru = 'Отладка обработчика ""После загрузки правил обмена"" не поддерживается.'");
				
			Иначе
				
				Выполнить(ТекстСобытияПослеЗагрузкиПравилОбмена);
				
			КонецЕсли;
			
		Исключение
			
			Текст = НСтр("ru = 'Обработчик: ""%1"": %2'");
			Текст = ПодставитьПараметрыВСтроку(Текст, "ПослеЗагрузкиПравилОбмена",
				ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
			
			ЗаписьЖурналаРегистрации(НСтр("ru = 'Универсальный обмен данными в формате XML'", КодОсновногоЯзыка()),
				УровеньЖурналаРегистрации.Ошибка,,, Текст);
				
			СообщитьПользователю(Текст);
			
		КонецПопытки;
		
	КонецЕсли;
	
КонецПроцедуры

Процедура ОбработатьОкончаниеЧтенияНовогоЭлемента(ПоследнийОбъектЗагрузки)
	
	мСчетчикЗагруженныхОбъектов = 1 + мСчетчикЗагруженныхОбъектов;
				
	Если ЗапоминатьЗагруженныеОбъекты
		И мСчетчикЗагруженныхОбъектов % 100 = 0 Тогда
				
		Если ЗагруженныеОбъекты.Количество() > ЧислоХранимыхЗагруженныхОбъектов Тогда
			ЗагруженныеОбъекты.Очистить();
		КонецЕсли;
				
	КонецЕсли;
	
	Если мСчетчикЗагруженныхОбъектов % 100 = 0
		И мГлобальныйСтекНеЗаписанныхОбъектов.Количество() > 100 Тогда
		
		ПровестиЗаписьНеЗаписанныхОбъектов();
		
	КонецЕсли;
	
	Если ИспользоватьТранзакции
		И КоличествоОбъектовНаТранзакцию > 0 
		И мСчетчикЗагруженныхОбъектов % КоличествоОбъектовНаТранзакцию = 0 Тогда
		
		ЗафиксироватьТранзакцию();
		НачатьТранзакцию();
		
	КонецЕсли;	

КонецПроцедуры

// Выполняет последовательное чтение файла сообщения обмена и записывает данные в информационную базу.
//
// Параметры:
//  РезультирующаяСтрокаСИнформациейОбОшибке - Строка - результирующая строка с информацией об ошибке.
// 
Процедура ПроизвестиЧтениеДанных(РезультирующаяСтрокаСИнформациейОбОшибке = "") Экспорт
	
	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	Попытка
	
		Пока ФайлОбмена.Прочитать() Цикл
			
			ИмяУзла = ФайлОбмена.ЛокальноеИмя;
			
			Если ИмяУзла = "Объект" Тогда
				
				ПоследнийОбъектЗагрузки = ПрочитатьОбъект();
				
				ОбработатьОкончаниеЧтенияНовогоЭлемента(ПоследнийОбъектЗагрузки);
				
			ИначеЕсли ИмяУзла = "ЗначениеПараметра" Тогда	
				
				ЗагрузитьЗначенияПараметровОбменаДанными();
				
			ИначеЕсли ИмяУзла = "АлгоритмПослеЗагрузкиПараметров" Тогда	
				
				Отказ = Ложь;
				ПричинаОтказа = "";
				
				ТекстАлгоритма = "";
				Конвертация.Свойство("ПослеЗагрузкиПараметров", ТекстАлгоритма);
				
				// При загрузке в безопасном режиме текст алгоритма получен при чтении правил.
				// В противном случае его следует получать из файла обмена.
				Если ПустаяСтрока(ТекстАлгоритма) Тогда
					ТекстАлгоритма = одЗначениеЭлемента(ФайлОбмена, одТипСтрока);
				Иначе
					ФайлОбмена.Пропустить();
				КонецЕсли;
				
				Если Не ПустаяСтрока(ТекстАлгоритма) Тогда
				
					Попытка
						
						Если ФлагРежимОтладкиОбработчиков Тогда
							
							ВызватьИсключение НСтр("ru = 'Отладка обработчика ""После загрузки параметров"" не поддерживается.'");
							
						Иначе
							
							Выполнить(ТекстАлгоритма);
							
						КонецЕсли;
						
						Если Отказ = Истина Тогда
							
							Если Не ПустаяСтрока(ПричинаОтказа) Тогда
								СтрокаИсключения = ПодставитьПараметрыВСтроку(НСтр("ru = 'Загрузка данных отменена по причине: %1'"), ПричинаОтказа);
								ВызватьИсключение СтрокаИсключения;
							Иначе
								ВызватьИсключение НСтр("ru = 'Загрузка данных отменена'");
							КонецЕсли;
							
						КонецЕсли;
						
					Исключение
												
						ЗП = ПолучитьСтруктуруЗаписиПротокола(75, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
						ЗП.Обработчик     = "ПослеЗагрузкиПараметров";
						СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(75, ЗП, Истина);
						
						Если Не ФлагРежимОтладки Тогда
							ВызватьИсключение СтрокаСообщенияОбОшибке;
						КонецЕсли;
						
					КонецПопытки;
					
				КонецЕсли;				
				
			ИначеЕсли ИмяУзла = "Алгоритм" Тогда
				
				ТекстАлгоритма = одЗначениеЭлемента(ФайлОбмена, одТипСтрока);
				
				Если Не ПустаяСтрока(ТекстАлгоритма) Тогда
				
					Попытка
						
						Если ФлагРежимОтладкиОбработчиков Тогда
							
							ВызватьИсключение НСтр("ru = 'Отладка глобального алгоритма не поддерживается.'");
							
						Иначе
							
							Выполнить(ТекстАлгоритма);
							
						КонецЕсли;
						
					Исключение
						
						ЗП = ПолучитьСтруктуруЗаписиПротокола(39, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
						ЗП.Обработчик     = "АлгоритмФайлаОбмена";
						СтрокаСообщенияОбОшибке = ЗаписатьВПротоколВыполнения(39, ЗП, Истина);
						
						Если Не ФлагРежимОтладки Тогда
							ВызватьИсключение СтрокаСообщенияОбОшибке;
						КонецЕсли;
						
					КонецПопытки;
					
				КонецЕсли;
				
			ИначеЕсли ИмяУзла = "ПравилаОбмена" Тогда
				
				мБылиПрочитаныПравилаОбменаПриЗагрузке = Истина;
				
				Если ТаблицаПравилКонвертации.Количество() = 0 Тогда
					ЗагрузитьПравилаОбмена(ФайлОбмена, "ЧтениеXML");
				Иначе
					одПропустить(ФайлОбмена);
				КонецЕсли;
				
			ИначеЕсли ИмяУзла = "ИнформацияОТипахДанных" Тогда
				
				ЗагрузитьИнформациюОТипахДанных();
				
			ИначеЕсли (ИмяУзла = "ФайлОбмена") И (ФайлОбмена.ТипУзла = одТипУзлаXML_КонецЭлемента) Тогда
				
			Иначе
				СтруктураЗаписи = Новый Структура("ИмяУзла", ИмяУзла);
				ЗаписатьВПротоколВыполнения(9, СтруктураЗаписи);
			КонецЕсли;
			
		КонецЦикла;
		
	Исключение
		
		СтрокаОшибки = ПодставитьПараметрыВСтроку(НСтр("ru = 'Ошибка при загрузке данных: %1'"),
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		
		РезультирующаяСтрокаСИнформациейОбОшибке = ЗаписатьВПротоколВыполнения(СтрокаОшибки, Неопределено, Истина, , , Истина);
		
		ЗавершитьВедениеПротоколаОбмена();
		ФайлОбмена.Закрыть();
		Возврат;
		
	КонецПопытки;
	
КонецПроцедуры

// Перед началом чтения данных из файла выполняем инициализацию переменных,
// загрузку правил обмена из файла данных,
// открываем транзакцию на запись данных в ИБ,
// выполняем необходимые обработчики событий.
//
// Параметры:
//  СтрокаДанных - Строка - имя файла для загрузки данных или строка-XML, содержащая данные для загрузки.
//
//  Возвращаемое значение:
//     Булево - Истина - загрузка данных из файла возможна; Ложь - нет.
//
Функция ВыполнитьДействияПередЧтениемДанных(СтрокаДанных = "") Экспорт
	
	РежимОбработкиДанных = мРежимыОбработкиДанных.Загрузка;

	мСоответствиеДопПараметровПоиска       = Новый Соответствие;
	мСоответствиеПравилКонвертации         = Новый Соответствие;
	
	Правила.Очистить();
	
	ИнициализироватьКомментарииПриВыгрузкеИЗагрузкеДанных();
	
	ИнициализироватьВедениеПротоколаОбмена();
	
	ЗагрузкаВозможна = Истина;
	
	Если ПустаяСтрока(СтрокаДанных) Тогда
	
		Если ПустаяСтрока(ИмяФайлаОбмена) Тогда
			ЗаписатьВПротоколВыполнения(15);
			ЗагрузкаВозможна = Ложь;
		КонецЕсли;
	
	КонецЕсли;
	
	// Инициализируем внешнюю обработку с экспортными обработчиками.
	ИнициализацияВнешнейОбработкиОбработчиковСобытий(ЗагрузкаВозможна, ЭтотОбъект);
	
	Если Не ЗагрузкаВозможна Тогда
		Возврат Ложь;
	КонецЕсли;
	
	СтрокаСообщения = ПодставитьПараметрыВСтроку(НСтр("ru = 'Начало загрузки: %1'"), ТекущаяДатаСеанса());
	ЗаписатьВПротоколВыполнения(СтрокаСообщения, , Ложь, , , Истина);
	
	Если ФлагРежимОтладки Тогда
		ИспользоватьТранзакции = Ложь;
	КонецЕсли;
	
	Если КоличествоОбработанныхОбъектовДляОбновленияСтатуса = 0 Тогда
		
		КоличествоОбработанныхОбъектовДляОбновленияСтатуса = 100;
		
	КонецЕсли;
	
	мСоответствиеТиповДанныхДляЗагрузки = Новый Соответствие;
	мГлобальныйСтекНеЗаписанныхОбъектов = Новый Соответствие;
	
	мСчетчикЗагруженныхОбъектов = 0;
	ФлагОшибки                  = Ложь;
	ЗагруженныеОбъекты          = Новый Соответствие;
	ЗагруженныеГлобальныеОбъекты = Новый Соответствие;

	ИнициализироватьМенеджерыИСообщения();
	
	ОткрытьФайлЗагрузки(,СтрокаДанных);
	
	Если ФлагОшибки Тогда 
		ЗавершитьВедениеПротоколаОбмена();
		Возврат Ложь; 
	КонецЕсли;

	// Определяем интерфейсы обработчиков.
	Если ФлагРежимОтладкиОбработчиков Тогда
		
		ДополнитьПравилаИнтерфейсамиОбработчиков(Конвертация, ТаблицаПравилКонвертации, ТаблицаПравилВыгрузки, ТаблицаПравилОчистки);
		
	КонецЕсли;
	
	// Обработчик ПередЗагрузкойДанных
	Отказ = Ложь;
	
	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	Если Не ПустаяСтрока(Конвертация.ПередЗагрузкойДанных) Тогда
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(Конвертация, "ПередЗагрузкойДанных"));
				
			Иначе
				
				Выполнить(Конвертация.ПередЗагрузкойДанных);
				
			КонецЕсли;
			
		Исключение
			
			ИмяОбработчика = НСтр("ru = '%1 (конвертация)'"); 
			ЗаписатьИнформациюОбОшибкеОбработчикиКонвертации(22, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), 
				ПодставитьПараметрыВСтроку(ИмяОбработчика, "ПередЗагрузкойДанных"));
			
			Отказ = Истина;
			
		КонецПопытки;
		
		Если Отказ Тогда // Отказ от загрузки данных
			ЗавершитьВедениеПротоколаОбмена();
			ФайлОбмена.Закрыть();
			ДеструкторВнешнейОбработкиОбработчиковСобытий();
			Возврат Ложь;
		КонецЕсли;
		
	КонецЕсли;

	// Очистка информационной базы по правилам.
	ОбработатьПравилаОчистки(ТаблицаПравилОчистки.Строки);
	
	Возврат Истина;
	
КонецФункции

// Процедура выполняет действия после итерации загрузки данных:
// - фиксация транзакции (при необходимости)
// - закрытие файла сообщения обмена
// - выполнение обработчика конвертации ПослеЗагрузкиДанных
// - завершение ведения протокола обмена (при необходимости).
//
// Параметры:
//  Нет.
// 
Процедура ВыполнитьДействияПослеЗавершенияЧтенияДанных() Экспорт
	
	Если БезопасныйРежим Тогда
		УстановитьБезопасныйРежим(Истина);
		Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
			УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
		КонецЦикла;
	КонецЕсли;
	
	ФайлОбмена.Закрыть();
	
	// Обработчик ПослеЗагрузкиДанных
	Если Не ПустаяСтрока(Конвертация.ПослеЗагрузкиДанных) Тогда
		
		Попытка
			
			Если ФлагРежимОтладкиОбработчиков Тогда
				
				Выполнить(ПолучитьСтрокуВызоваОбработчика(Конвертация, "ПослеЗагрузкиДанных"));
				
			Иначе
				
				Выполнить(Конвертация.ПослеЗагрузкиДанных);
				
			КонецЕсли;
			
		Исключение
			
			ИмяОбработчика = НСтр("ru = '%1 (конвертация)'");
			ЗаписатьИнформациюОбОшибкеОбработчикиКонвертации(23, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), 
				ПодставитьПараметрыВСтроку(ИмяОбработчика, "ПослеЗагрузкиДанных"));
			
		КонецПопытки;
		
	КонецЕсли;
	
	ДеструкторВнешнейОбработкиОбработчиковСобытий();
	
	ЗаписатьВПротоколВыполнения(ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Окончание загрузки: %1'"), ТекущаяДатаСеанса()), , Ложь, , , Истина);
	ЗаписатьВПротоколВыполнения(ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Загружено объектов: %1'"), мСчетчикЗагруженныхОбъектов), , Ложь, , , Истина);
	
	ЗавершитьВедениеПротоколаОбмена();
	
	Если ЭтоИнтерактивныйРежим Тогда
		СообщитьПользователю(НСтр("ru = 'Загрузка данных завершена.'"));
	КонецЕсли;
	
КонецПроцедуры

// Выполняет загрузку данных в соответствии с установленными режимами (правилами обмена).
//
// Параметры:
//  Нет.
//
Процедура ВыполнитьЗагрузку() Экспорт
	
	РаботаВозможна = ВыполнитьДействияПередЧтениемДанных();
	
	Если Не РаботаВозможна Тогда
		Возврат;
	КонецЕсли;
	
	Если ИспользоватьТранзакции Тогда
		НачатьТранзакцию();
	КонецЕсли;
	
	Попытка
		ПроизвестиЧтениеДанных();
		// Отложенная запись того, что не записали с самого начала.
		ПровестиЗаписьНеЗаписанныхОбъектов();
		Если ИспользоватьТранзакции Тогда
			ЗафиксироватьТранзакцию();
		КонецЕсли;
	Исключение
		Если ИспользоватьТранзакции Тогда
			ОтменитьТранзакцию();
		КонецЕсли;
	КонецПопытки;
	
	ВыполнитьДействияПослеЗавершенияЧтенияДанных();
	
КонецПроцедуры

Процедура СжатьРезультирующийФайлОбмена()
	
	Попытка
		
		ИмяИсходногоФайлаОбмена = ИмяФайлаОбмена;
		Если АрхивироватьФайл Тогда
			ИмяФайлаОбмена = СтрЗаменить(ИмяФайлаОбмена, ".xml", ".zip");
		КонецЕсли;
		
		Архиватор = Новый ЗаписьZipФайла(ИмяФайлаОбмена, ПарольДляСжатияФайлаОбмена, НСтр("ru = 'Файл обмена данными'"));
		Архиватор.Добавить(ИмяИсходногоФайлаОбмена);
		Архиватор.Записать();
		
		УдалитьФайлы(ИмяИсходногоФайлаОбмена);
		
	Исключение
		ЗаписьЖурналаРегистрации(НСтр("ru = 'Универсальный обмен данными в формате XML'", КодОсновногоЯзыка()),
			УровеньЖурналаРегистрации.Ошибка,,, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
	КонецПопытки;
	
КонецПроцедуры

Функция РаспаковатьZipФайл(ИмяФайлаДляРаспаковки)
	
	КаталогДляРаспаковки = ВременныйКаталогРаботыСФайлами;
	СоздатьКаталог(КаталогДляРаспаковки);
	
	ИмяРаспакованногоФайла = "";
	
	Попытка
		
		Архиватор = Новый ЧтениеZipФайла(ИмяФайлаДляРаспаковки, ПарольДляРаспаковкиФайлаОбмена);
		
		Если Архиватор.Элементы.Количество() > 0 Тогда
			
			ЭлементАрхива = Архиватор.Элементы.Получить(0);
			
			Архиватор.Извлечь(ЭлементАрхива, КаталогДляРаспаковки, РежимВосстановленияПутейФайловZIP.НеВосстанавливать);
			ИмяРаспакованногоФайла = ПолучитьИмяФайлаОбмена(КаталогДляРаспаковки, ЭлементАрхива.Имя);
			
		Иначе
			
			ИмяРаспакованногоФайла = "";
			
		КонецЕсли;
		
		Архиватор.Закрыть();
	
	Исключение
		
		ЗП = ПолучитьСтруктуруЗаписиПротокола(2, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		ЗаписатьВПротоколВыполнения(2, ЗП, Истина);
		
		Возврат "";
							
	КонецПопытки;
	
	Возврат ИмяРаспакованногоФайла;
		
КонецФункции

Функция ВыполнитьПередачуИнформацииОНачалеОбменаВПриемник(ТекущаяСтрокаДляЗаписи)
	
	Если НЕ НепосредственноеЧтениеВИБПриемнике Тогда
		Возврат Истина;
	КонецЕсли;
	
	ТекущаяСтрокаДляЗаписи = ТекущаяСтрокаДляЗаписи + Символы.ПС + мXMLПравила + Символы.ПС + "</ФайлОбмена>" + Символы.ПС;
	
	РаботаВозможна = мОбработкаДляЗагрузкиДанных.ВыполнитьДействияПередЧтениемДанных(ТекущаяСтрокаДляЗаписи);
	
	Возврат РаботаВозможна;	
	
КонецФункции

Функция ВыполнитьПередачуИнформацииПриЗавершенииПередачиДанных()
	
	Если НЕ НепосредственноеЧтениеВИБПриемнике Тогда
		Возврат Истина;
	КонецЕсли;
	
	мОбработкаДляЗагрузкиДанных.ВыполнитьДействияПослеЗавершенияЧтенияДанных();
	
КонецФункции

Процедура ПередатьДополнительныеПараметрыВПриемник()
	
	Для Каждого Параметр Из ТаблицаНастройкиПараметров Цикл
		
		Если Параметр.ПередаватьПараметрПриВыгрузке = Истина Тогда
			
			ПередатьОдинПараметрВПриемник(Параметр.Имя, Параметр.Значение, Параметр.ПравилоКонвертации);
					
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

Процедура ПередатьИнформациюОТипахВПриемник()
	
	Если Не ПустаяСтрока(мСтрокаТиповДляПриемника) Тогда
		ЗаписатьВФайл(мСтрокаТиповДляПриемника);
	КонецЕсли;
		
КонецПроцедуры

// Выполняет выгрузку данных в соответствии с установленными режимами (правилами обмена).
//
// Параметры:
//  Нет.
//
Процедура ВыполнитьВыгрузку() Экспорт
	
	РежимОбработкиДанных = мРежимыОбработкиДанных.Выгрузка;
	
	ИнициализироватьВедениеПротоколаОбмена();
	
	ИнициализироватьКомментарииПриВыгрузкеИЗагрузкеДанных();
	
	ВыгрузкаВозможна = Истина;
	ТекущийУровеньВложенностиВыгрузитьПоПравилу = 0;
	
	мСтекВызововВыгрузкиДанных = Новый ТаблицаЗначений;
	мСтекВызововВыгрузкиДанных.Колонки.Добавить("Ссылка");
	мСтекВызововВыгрузкиДанных.Индексы.Добавить("Ссылка");
	
	Если мБылиПрочитаныПравилаОбменаПриЗагрузке = Истина Тогда
		
		ЗаписатьВПротоколВыполнения(74);
		ВыгрузкаВозможна = Ложь;	
		
	КонецЕсли;
	
	Если ПустаяСтрока(ИмяФайлаПравилОбмена) Тогда
		ЗаписатьВПротоколВыполнения(12);
		ВыгрузкаВозможна = Ложь;
	КонецЕсли;
	
	Если НЕ НепосредственноеЧтениеВИБПриемнике Тогда
		
		Если ПустаяСтрока(ИмяФайлаОбмена) Тогда
			ЗаписатьВПротоколВыполнения(10);
			ВыгрузкаВозможна = Ложь;
		КонецЕсли;
		
	Иначе
		
		мОбработкаДляЗагрузкиДанных = ВыполнитьПодключениеКИБПриемнику(); 
		
		ВыгрузкаВозможна = мОбработкаДляЗагрузкиДанных <> Неопределено;
		
	КонецЕсли;
	
	// Инициализируем внешнюю обработку с экспортными обработчиками.
	ИнициализацияВнешнейОбработкиОбработчиковСобытий(ВыгрузкаВозможна, ЭтотОбъект);
	
	Если Не ВыгрузкаВозможна Тогда
		мОбработкаДляЗагрузкиДанных = Неопределено;
		Возврат;
	КонецЕсли;
	
	ЗаписатьВПротоколВыполнения(ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Начало выгрузки: %1'"), ТекущаяДатаСеанса()), , Ложь, , , Истина);
		
	ИнициализироватьМенеджерыИСообщения();
	
	мСчетчикВыгруженныхОбъектов = 0;
	мСчетчикНПП 				= 0;
	ФлагОшибки                  = Ложь;

	// Загрузка правил обмена
	Если Конвертация.Количество() = 9 Тогда
		
		ЗагрузитьПравилаОбмена();
		Если ФлагОшибки Тогда
			ЗавершитьВедениеПротоколаОбмена();
			мОбработкаДляЗагрузкиДанных = Неопределено;
			Возврат;
		КонецЕсли;
		
	Иначе
		
		Для каждого Правило Из ТаблицаПравилКонвертации Цикл
			Правило.Выгруженные.Очистить();
			Правило.ВыгруженныеТолькоСсылки.Очистить();
		КонецЦикла;
		
	КонецЕсли;

	// Присваиваем параметры установленные в диалоге.
	УстановитьПараметрыИзДиалога();

	// Открываем файл обмена
	ТекущаяСтрокаДляЗаписи = ОткрытьФайлВыгрузки() + Символы.ПС;
	
	Если ФлагОшибки Тогда
		ФайлОбмена = Неопределено;
		ЗавершитьВедениеПротоколаОбмена();
		мОбработкаДляЗагрузкиДанных = Неопределено;
		Возврат; 
	КонецЕсли;
	
	// Определяем интерфейсы обработчиков.
	Если ФлагРежимОтладкиОбработчиков Тогда
		
		ДополнитьПравилаИнтерфейсамиОбработчиков(Конвертация, ТаблицаПравилКонвертации, ТаблицаПравилВыгрузки, ТаблицаПравилОчистки);
		
	КонецЕсли;
	
	Если ИспользоватьТранзакции Тогда
		НачатьТранзакцию();
	КонецЕсли;
	
	Отказ = Ложь;
	
	Попытка
	
		// Включаем правила обмена в файл.
		ФайлОбмена.ЗаписатьСтроку(мXMLПравила);
		
		Отказ = Не ВыполнитьПередачуИнформацииОНачалеОбменаВПриемник(ТекущаяСтрокаДляЗаписи);
		
		Если Не Отказ Тогда
			
			Если БезопасныйРежим Тогда
				УстановитьБезопасныйРежим(Истина);
				Для Каждого ИмяРазделителя Из РазделителиКонфигурации Цикл
					УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина);
				КонецЦикла;
			КонецЕсли;
			
			// Обработчик ПередВыгрузкойДанных
			Попытка
				
				Если ФлагРежимОтладкиОбработчиков Тогда
					
					Если Не ПустаяСтрока(Конвертация.ПередВыгрузкойДанных) Тогда
						
						Выполнить(ПолучитьСтрокуВызоваОбработчика(Конвертация, "ПередВыгрузкойДанных"));
						
					КонецЕсли;
					
				Иначе
					
					Выполнить(Конвертация.ПередВыгрузкойДанных);
					
				КонецЕсли;
				
			Исключение
				
				ИмяОбработчика = НСтр("ru = '%1 (конвертация)'");
				ЗаписатьИнформациюОбОшибкеОбработчикиКонвертации(62, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), 
					ПодставитьПараметрыВСтроку(ИмяОбработчика, "ПередВыгрузкойДанных"));
					
				Отказ = Истина;
				
			КонецПопытки;
			
			Если Не Отказ Тогда
				
				Если ВыполнитьОбменДаннымиВОптимизированномФормате Тогда
					ПередатьИнформациюОТипахВПриемник();
				КонецЕсли;
				
				// Нужно параметры передать в приемник.
				ПередатьДополнительныеПараметрыВПриемник();
				
				ТекстСобытияПослеЗагрузкиПараметров = "";
				Если Конвертация.Свойство("ПослеЗагрузкиПараметров", ТекстСобытияПослеЗагрузкиПараметров)
					И Не ПустаяСтрока(ТекстСобытияПослеЗагрузкиПараметров) Тогда
					
					ЗаписьСобытия = Новый ЗаписьXML;
					ЗаписьСобытия.УстановитьСтроку();
					одЗаписатьЭлемент(ЗаписьСобытия, "АлгоритмПослеЗагрузкиПараметров", ТекстСобытияПослеЗагрузкиПараметров);
					ЗаписатьВФайл(ЗаписьСобытия);
					
				КонецЕсли;
				
				СоответствиеУзловИПравилВыгрузки = Новый Соответствие();
				СтруктураДляУдаленияРегистрацииИзменений = Новый Соответствие();
				
				ОбработатьПравилаВыгрузки(КоллекцияПравилаВыгрузки().Строки, СоответствиеУзловИПравилВыгрузки);
				
				УдачноВыгруженоПоПланамОбмена = ОбработатьВыгрузкуДляПлановОбмена(СоответствиеУзловИПравилВыгрузки, СтруктураДляУдаленияРегистрацииИзменений);
				
				Если УдачноВыгруженоПоПланамОбмена Тогда
				
					ОбработатьИзменениеРегистрацииДляУзловОбмена(СтруктураДляУдаленияРегистрацииИзменений);
				
				КонецЕсли;
				
				// Обработчик ПослеВыгрузкиДанных
				Попытка
					
					Если ФлагРежимОтладкиОбработчиков Тогда
						
						Если Не ПустаяСтрока(Конвертация.ПослеВыгрузкиДанных) Тогда
							
							Выполнить(ПолучитьСтрокуВызоваОбработчика(Конвертация, "ПослеВыгрузкиДанных"));
							
						КонецЕсли;
						
					Иначе
						
						Выполнить(Конвертация.ПослеВыгрузкиДанных);
						
					КонецЕсли;

				Исключение
					
					ИмяОбработчика = НСтр("ru = '%1 (конвертация)'");
					ЗаписатьИнформациюОбОшибкеОбработчикиКонвертации(63, ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()), 
						ПодставитьПараметрыВСтроку(ИмяОбработчика, "ПослеВыгрузкиДанных"));
					
				КонецПопытки;
				
				ПровестиЗаписьНеЗаписанныхОбъектов();
				
				Если ТранзакцияАктивна() Тогда
					ЗафиксироватьТранзакцию();
				КонецЕсли;
				
			КонецЕсли;
			
		КонецЕсли;
		
		Если Отказ Тогда
			
			Если ТранзакцияАктивна() Тогда
				ОтменитьТранзакцию();
			КонецЕсли;
			
			ВыполнитьПередачуИнформацииПриЗавершенииПередачиДанных();
			
			ЗавершитьВедениеПротоколаОбмена();
			мОбработкаДляЗагрузкиДанных = Неопределено;
			ФайлОбмена = Неопределено;
			
			ДеструкторВнешнейОбработкиОбработчиковСобытий();
			
		КонецЕсли;
		
	Исключение
		
		Если ТранзакцияАктивна() Тогда
			ОтменитьТранзакцию();
		КонецЕсли;
		
		Отказ = Истина;
		СтрокаОшибки = ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		
		ЗаписатьВПротоколВыполнения(ПодставитьПараметрыВСтроку(
			НСтр("ru = 'Ошибка при выгрузке данных: %1'"), СтрокаОшибки), Неопределено, Истина, , , Истина);
		
		ВыполнитьПередачуИнформацииПриЗавершенииПередачиДанных();
		
		ЗавершитьВедениеПротоколаОбмена();
		ЗакрытьФайл();
		мОбработкаДляЗагрузкиДанных = Неопределено;
				
	КонецПопытки;
	
	Если Отказ Тогда
		Возврат;
	КонецЕсли;
	
	// Закрываем файл обмена
	ЗакрытьФайл();
	
	Если АрхивироватьФайл Тогда
		СжатьРезультирующийФайлОбмена();
	КонецЕсли;
	
	ВыполнитьПередачуИнформацииПриЗавершенииПередачиДанных();
	
	ЗаписатьВПротоколВыполнения(ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Окончание выгрузки: %1'"), ТекущаяДатаСеанса()), , Ложь, , ,Истина);
	ЗаписатьВПротоколВыполнения(ПодставитьПараметрыВСтроку(
		НСтр("ru = 'Выгружено объектов: %1'"), мСчетчикВыгруженныхОбъектов), , Ложь, , , Истина);
	
	ЗавершитьВедениеПротоколаОбмена();
	
	мОбработкаДляЗагрузкиДанных = Неопределено;
	
	ДеструкторВнешнейОбработкиОбработчиковСобытий();
	
	Если ЭтоИнтерактивныйРежим Тогда
		СообщитьПользователю(НСтр("ru = 'Выгрузка данных завершена.'"));
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область УстановкаЗначенийРеквизитовИМодальныхПеременныхОбработки

// Процедура установки значения глобальной переменной "ФлагОшибки".
//
// Параметры:
//  Значение - Булево - новое значение переменной "ФлагОшибки".
//  
Процедура УстановитьФлагОшибки(Значение)
	
	ФлагОшибки = Значение;
	
	Если ФлагОшибки Тогда
		
		ДеструкторВнешнейОбработкиОбработчиковСобытий(ФлагРежимОтладки);
		
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#Область ИнициализацияТаблицПравилОбмена

Процедура ДобавитьНедостающиеКолонки(Колонки, Имя, Типы = Неопределено)
	
	Если Колонки.Найти(Имя) <> Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Колонки.Добавить(Имя, Типы);
	
КонецПроцедуры

// Инициализирует колонки таблицы правил конвертации объектов.
//
// Параметры:
//  Нет.
// 
Процедура ИнициализацияТаблицыПравилКонвертации()

	Колонки = ТаблицаПравилКонвертации.Колонки;
	
	ДобавитьНедостающиеКолонки(Колонки, "Имя");
	ДобавитьНедостающиеКолонки(Колонки, "Наименование");
	ДобавитьНедостающиеКолонки(Колонки, "Порядок");

	ДобавитьНедостающиеКолонки(Колонки, "СинхронизироватьПоИдентификатору");
	ДобавитьНедостающиеКолонки(Колонки, "НеСоздаватьЕслиНеНайден", одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "НеВыгружатьОбъектыСвойствПоСсылкам", одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ПродолжитьПоискПоПолямПоискаЕслиПоИдентификаторуНеНашли", одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ПриПереносеОбъектаПоСсылкеУстанавливатьТолькоGIUD", одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ИспользоватьБыстрыйПоискПриЗагрузке", одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ГенерироватьНовыйНомерИлиКодЕслиНеУказан", одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "МаленькоеКоличествоОбъектов", одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "КоличествоОбращенийДляВыгрузкиСсылки", одОписаниеТипа("Число"));
	ДобавитьНедостающиеКолонки(Колонки, "КоличествоЭлементовВИБ", одОписаниеТипа("Число"));
	
	ДобавитьНедостающиеКолонки(Колонки, "СпособВыгрузки");

	ДобавитьНедостающиеКолонки(Колонки, "Источник");
	ДобавитьНедостающиеКолонки(Колонки, "Приемник");
	
	ДобавитьНедостающиеКолонки(Колонки, "ТипИсточника",  одОписаниеТипа("Строка"));

	ДобавитьНедостающиеКолонки(Колонки, "ПередВыгрузкой");
	ДобавитьНедостающиеКолонки(Колонки, "ПриВыгрузке");
	ДобавитьНедостающиеКолонки(Колонки, "ПослеВыгрузки");
	ДобавитьНедостающиеКолонки(Колонки, "ПослеВыгрузкиВФайл");
	
	ДобавитьНедостающиеКолонки(Колонки, "ЕстьОбработчикПередВыгрузкой",	    одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ЕстьОбработчикПриВыгрузке",		одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ЕстьОбработчикПослеВыгрузки",		одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ЕстьОбработчикПослеВыгрузкиВФайл",	одОписаниеТипа("Булево"));

	ДобавитьНедостающиеКолонки(Колонки, "ПередЗагрузкой");
	ДобавитьНедостающиеКолонки(Колонки, "ПриЗагрузке");
	ДобавитьНедостающиеКолонки(Колонки, "ПослеЗагрузки");
	
	ДобавитьНедостающиеКолонки(Колонки, "ПоследовательностьПолейПоиска");
	ДобавитьНедостающиеКолонки(Колонки, "ПоискПоТабличнымЧастям");
	
	ДобавитьНедостающиеКолонки(Колонки, "ЕстьОбработчикПередЗагрузкой", одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ЕстьОбработчикПриЗагрузке",    одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ЕстьОбработчикПослеЗагрузки",  одОписаниеТипа("Булево"));
	
	ДобавитьНедостающиеКолонки(Колонки, "ЕстьОбработчикПоследовательностьПолейПоиска",  одОписаниеТипа("Булево"));

	ДобавитьНедостающиеКолонки(Колонки, "СвойстваПоиска",	одОписаниеТипа("ТаблицаЗначений"));
	ДобавитьНедостающиеКолонки(Колонки, "Свойства",		одОписаниеТипа("ТаблицаЗначений"));
	
	ДобавитьНедостающиеКолонки(Колонки, "Значения",		одОписаниеТипа("Соответствие"));

	ДобавитьНедостающиеКолонки(Колонки, "Выгруженные",							одОписаниеТипа("Соответствие"));
	ДобавитьНедостающиеКолонки(Колонки, "ВыгруженныеТолькоСсылки",				одОписаниеТипа("Соответствие"));
	ДобавитьНедостающиеКолонки(Колонки, "ВыгружатьПредставлениеИсточника",		одОписаниеТипа("Булево"));
	
	ДобавитьНедостающиеКолонки(Колонки, "НеЗамещать",					одОписаниеТипа("Булево"));
	
	ДобавитьНедостающиеКолонки(Колонки, "ЗапоминатьВыгруженные",       одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ВсеОбъектыВыгружены",         одОписаниеТипа("Булево"));
	
КонецПроцедуры

// Инициализирует колонки таблицы правил выгрузки данных.
//
// Параметры:
//  Нет
// 
Процедура ИнициализацияТаблицыПравилВыгрузки()

	Колонки = ТаблицаПравилВыгрузки.Колонки;

	ДобавитьНедостающиеКолонки(Колонки, "Включить",		одОписаниеТипа("Число"));
	ДобавитьНедостающиеКолонки(Колонки, "ЭтоГруппа",		одОписаниеТипа("Булево"));
	
	ДобавитьНедостающиеКолонки(Колонки, "Имя");
	ДобавитьНедостающиеКолонки(Колонки, "Наименование");
	ДобавитьНедостающиеКолонки(Колонки, "Порядок");

	ДобавитьНедостающиеКолонки(Колонки, "СпособОтбораДанных");
	ДобавитьНедостающиеКолонки(Колонки, "ОбъектВыборки");
	
	ДобавитьНедостающиеКолонки(Колонки, "ПравилоКонвертации");

	ДобавитьНедостающиеКолонки(Колонки, "ПередОбработкой");
	ДобавитьНедостающиеКолонки(Колонки, "ПослеОбработки");

	ДобавитьНедостающиеКолонки(Колонки, "ПередВыгрузкой");
	ДобавитьНедостающиеКолонки(Колонки, "ПослеВыгрузки");
	
	// Колонки для поддержки отбора с помощью построителя.
	ДобавитьНедостающиеКолонки(Колонки, "ИспользоватьОтбор", одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "НастройкиПостроителя");
	ДобавитьНедостающиеКолонки(Колонки, "ИмяОбъектаДляЗапроса");
	ДобавитьНедостающиеКолонки(Колонки, "ИмяОбъектаДляЗапросаРегистра");
	
	ДобавитьНедостающиеКолонки(Колонки, "ВыбиратьДанныеДляВыгрузкиОднимЗапросом", одОписаниеТипа("Булево"));
	
	ДобавитьНедостающиеКолонки(Колонки, "СсылкаНаУзелОбмена");

КонецПроцедуры

// Инициализирует колонки таблицы правил очистки данных.
//
// Параметры:
//  Нет.
// 
Процедура ИнициализацияТаблицыПравилОчистки()

	Колонки = ТаблицаПравилОчистки.Колонки;

	ДобавитьНедостающиеКолонки(Колонки, "Включить",		одОписаниеТипа("Булево"));
	ДобавитьНедостающиеКолонки(Колонки, "ЭтоГруппа",		одОписаниеТипа("Булево"));
	
	ДобавитьНедостающиеКолонки(Колонки, "Имя");
	ДобавитьНедостающиеКолонки(Колонки, "Наименование");
	ДобавитьНедостающиеКолонки(Колонки, "Порядок",	одОписаниеТипа("Число"));

	ДобавитьНедостающиеКолонки(Колонки, "СпособОтбораДанных");
	ДобавитьНедостающиеКолонки(Колонки, "ОбъектВыборки");
	
	ДобавитьНедостающиеКолонки(Колонки, "УдалятьЗаПериод");
	ДобавитьНедостающиеКолонки(Колонки, "Непосредственно",	одОписаниеТипа("Булево"));

	ДобавитьНедостающиеКолонки(Колонки, "ПередОбработкой");
	ДобавитьНедостающиеКолонки(Колонки, "ПослеОбработки");
	ДобавитьНедостающиеКолонки(Колонки, "ПередУдалением");
	
КонецПроцедуры

// Инициализирует колонки таблицы настройки параметров.
//
// Параметры:
//  Нет.
// 
Процедура ИнициализацияТаблицыНастройкиПараметров()

	Колонки = ТаблицаНастройкиПараметров.Колонки;

	ДобавитьНедостающиеКолонки(Колонки, "Имя");
	ДобавитьНедостающиеКолонки(Колонки, "Наименование");
	ДобавитьНедостающиеКолонки(Колонки, "Значение");
	ДобавитьНедостающиеКолонки(Колонки, "ПередаватьПараметрПриВыгрузке");
	ДобавитьНедостающиеКолонки(Колонки, "ПравилоКонвертации");

КонецПроцедуры

#КонецОбласти

#Область ИнициализацияРеквизитовИМодульныхПеременных

Процедура ИнициализироватьКомментарииПриВыгрузкеИЗагрузкеДанных()
	
	КомментарийПриВыгрузкеДанных = "";
	КомментарийПриЗагрузкеДанных = "";
	
КонецПроцедуры

// Инициализирует переменную одСообщения, содержащую соответствия кодов сообщений их описаниям.
//
// Параметры:
//  Нет.
// 
Процедура ИнициализацияСообщений()

	одСообщения = Новый Соответствие;
	
	одСообщения.Вставить(2,  НСтр("ru = 'Ошибка распаковки файла обмена. Файл заблокирован'"));
	одСообщения.Вставить(3,  НСтр("ru = 'Указанный файл правил обмена не существует'"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка при создании COM-объекта %1'");
	одСообщения.Вставить(4,  ПодставитьПараметрыВСтроку(ТекстОшибки,"Msxml2.DOMDocument"));
	
	одСообщения.Вставить(5,  НСтр("ru = 'Ошибка открытия файла обмена'"));
	одСообщения.Вставить(6,  НСтр("ru = 'Ошибка при загрузке правил обмена'"));
	одСообщения.Вставить(7,  НСтр("ru = 'Ошибка формата правил обмена'"));
	одСообщения.Вставить(8,  НСтр("ru = 'Некорректно указано имя файла для выгрузки данных'"));
	одСообщения.Вставить(9,  НСтр("ru = 'Ошибка формата файла обмена'"));
	одСообщения.Вставить(10, НСтр("ru = 'Не указано имя файла для выгрузки данных (Имя файла данных)'"));
	одСообщения.Вставить(11, НСтр("ru = 'Ссылка на несуществующий объект метаданных в правилах обмена'"));
	одСообщения.Вставить(12, НСтр("ru = 'Не указано имя файла с правилами обмена (Имя файла правил)'"));
	
	одСообщения.Вставить(13, НСтр("ru = 'Ошибка получения значения свойства объекта (по имени свойства источника)'"));
	одСообщения.Вставить(14, НСтр("ru = 'Ошибка получения значения свойства объекта (по имени свойства приемника)'"));
	
	одСообщения.Вставить(15, НСтр("ru = 'Не указано имя файла для загрузки данных (Имя файла для загрузки)'"));
	
	одСообщения.Вставить(16, НСтр("ru = 'Ошибка получения значения свойства подчиненного объекта (по имени свойства источника)'"));
	одСообщения.Вставить(17, НСтр("ru = 'Ошибка получения значения свойства подчиненного объекта (по имени свойства приемника)'"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка в обработчике события %1'");
	одСообщения.Вставить(19, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПередЗагрузкойОбъекта"));
	одСообщения.Вставить(20, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПриЗагрузкеОбъекта"));
	одСообщения.Вставить(21, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПослеЗагрузкиОбъекта"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка в обработчике события %1 (конвертация)'");
	одСообщения.Вставить(22, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПередЗагрузкойДанных"));
	одСообщения.Вставить(23, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПослеЗагрузкиДанных"));
	
	одСообщения.Вставить(24, НСтр("ru = 'Ошибка при удалении объекта'"));
	одСообщения.Вставить(25, НСтр("ru = 'Ошибка при записи документа'"));
	одСообщения.Вставить(26, НСтр("ru = 'Ошибка записи объекта'"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка в обработчике события %1'");
	одСообщения.Вставить(27, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПередОбработкойПравилаВыгрузки"));
	одСообщения.Вставить(28, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПослеОбработкиПравилаОчистки"));
	одСообщения.Вставить(29, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПередУдалениемОбъекта"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка в обработчике события %1'");
	одСообщения.Вставить(31, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПередОбработкойПравилаВыгрузки"));
	одСообщения.Вставить(32, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПослеОбработкиПравилаВыгрузки"));
	одСообщения.Вставить(33, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПередВыгрузкойОбъекта"));
	одСообщения.Вставить(34, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПослеВыгрузкиОбъекта"));
	
	одСообщения.Вставить(39, НСтр("ru = 'Ошибка при выполнении алгоритма, содержащегося в файле обмена'"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка в обработчике события %1'");
	одСообщения.Вставить(41, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПередВыгрузкойОбъекта"));
	одСообщения.Вставить(42, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПриВыгрузкеОбъекта"));
	одСообщения.Вставить(43, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПослеВыгрузкиОбъекта"));
	
	одСообщения.Вставить(45, НСтр("ru = 'Не найдено правило конвертации объектов'"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка в обработчике события %1 группы свойств'");
	одСообщения.Вставить(48, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПередОбработкойВыгрузки"));
	одСообщения.Вставить(49, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПослеОбработкиВыгрузки"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка в обработчике события %1 (объекта коллекции)'");
	одСообщения.Вставить(50, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПередВыгрузкой"));
	одСообщения.Вставить(51, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПриВыгрузке"));
	одСообщения.Вставить(52, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПослеВыгрузки"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка в глобальном обработчике события %1 (конвертация)'"); 
	одСообщения.Вставить(53, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПередЗагрузкойОбъекта"));
	одСообщения.Вставить(54, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПослеЗагрузкиОбъекта"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка в обработчике события %1 (свойства)'");
	одСообщения.Вставить(55, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПередВыгрузкой"));
	одСообщения.Вставить(56, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПриВыгрузке"));
	одСообщения.Вставить(57, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПослеВыгрузки"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка в обработчике события %1 (конвертация)'");
	одСообщения.Вставить(62, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПередВыгрузкойДанных"));
	одСообщения.Вставить(63, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПослеВыгрузкиДанных"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка в глобальном обработчике события %1 (конвертация)'");
	одСообщения.Вставить(64,  ПодставитьПараметрыВСтроку(ТекстОшибки, "ПередКонвертациейОбъекта"));
	одСообщения.Вставить(65, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПередВыгрузкойОбъекта"));
	
	одСообщения.Вставить(66, НСтр("ru = 'Ошибка получения коллекции подчиненных объектов из входящих данных'"));
	одСообщения.Вставить(67, НСтр("ru = 'Ошибка получения свойства подчиненного объекта из входящих данных'"));
	одСообщения.Вставить(68, НСтр("ru = 'Ошибка получения свойства объекта из входящих данных'"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка в глобальном обработчике события %1 (конвертация)'");
	одСообщения.Вставить(69, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПослеВыгрузкиОбъекта"));
	
	одСообщения.Вставить(71, НСтр("ru = 'Не найдено соответствие для значения Источника'"));
	
	одСообщения.Вставить(72, НСтр("ru = 'Ошибка при выгрузке данных для узла плана обмена'"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка в обработчике события %1'");
	одСообщения.Вставить(73, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПоследовательностьПолейПоиска"));
	
	одСообщения.Вставить(74, НСтр("ru = 'Необходимо перезагрузить правила обмена для выгрузки данных'"));
	
	одСообщения.Вставить(75, НСтр("ru = 'Ошибка при выполнении алгоритма после загрузки значений параметров'"));
	
	ТекстОшибки = НСтр("ru = 'Ошибка в обработчике события %1'");
	одСообщения.Вставить(76, ПодставитьПараметрыВСтроку(ТекстОшибки, "ПослеВыгрузкиОбъектаВФайл"));
	
	одСообщения.Вставить(77, НСтр("ru = 'Не указан файл внешней обработки с подключаемыми процедурами обработчиков событий'"));
	
	одСообщения.Вставить(78, НСтр("ru = 'Ошибка создания внешней обработки из файла с процедурами обработчиков событий'"));
	
	одСообщения.Вставить(79, НСтр("ru = 'Код алгоритмов не может быть интегрирован в обработчик из-за обнаруженного рекурсивного вызова алгоритмов. 
	                         |Если в процессе отладки нет необходимости отлаживать код алгоритмов, то укажите режим ""не отлаживать алгоритмы""
	                         |Если необходимо выполнять отладку алгоритмов с рекурсивным вызовом, то укажите режим  ""алгоритмы отлаживать как процедуры"" 
	                         |и повторите выгрузку.'"));
	
	одСообщения.Вставить(80, НСтр("ru = 'Обмен данными можно проводить только под полными правами'"));
	
	одСообщения.Вставить(1000, НСтр("ru = 'Ошибка при создании временного файла выгрузки данных'"));

КонецПроцедуры

Процедура ДополнитьМассивМенеджеровСсылочнымТипом(Менеджеры, МенеджерыДляПлановОбмена, ОбъектМД, ИмяТипа, Менеджер, ПрефиксИмениТипа, ВозможенПоискПоПредопределенным = Ложь)
	
	Имя              = ОбъектМД.Имя;
	ТипСсылкиСтрокой = ПрефиксИмениТипа + "." + Имя;
	
	ТекстЗапроса = 
	"ВЫБРАТЬ
	|	ПсевдонимТаблицыМетаданных.Ссылка
	|ИЗ
	|	&ИмяТаблицыМетаданных КАК ПсевдонимТаблицыМетаданных
	|ГДЕ
	|	&ПараметрАвтозаменыДляОбнуленияСекцииУсловий";
	
	СтрокаЗамены = "";
	СтрокаЗамены = ПодставитьПараметрыВСтроку("%1.%2", ИмяТипа, Имя);
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяТаблицыМетаданных", СтрокаЗамены);
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ПараметрАвтозаменыДляОбнуленияСекцииУсловий", "");
	
	СтрокаПоиска     = ТекстЗапроса;
	ТипСсылки        = Тип(ТипСсылкиСтрокой);
	Структура = СтруктураПараметровМенеджера(Имя, ИмяТипа, ТипСсылкиСтрокой, Менеджер, ОбъектМД);
	Структура.Вставить("ВозможенПоискПоПредопределенным", ВозможенПоискПоПредопределенным);
	Структура.Вставить("СтрокаПоиска", СтрокаПоиска);
	Менеджеры.Вставить(ТипСсылки, Структура);
	
	СтруктураДляПланаОбмена = СтруктураПараметровПланаОбмена(Имя, ТипСсылки, Истина, Ложь);
	МенеджерыДляПлановОбмена.Вставить(ОбъектМД, СтруктураДляПланаОбмена);
	
КонецПроцедуры

Процедура ДополнитьМассивМенеджеровТипомРегистра(Менеджеры, ОбъектМД, ИмяТипа, Менеджер, ПрефиксИмениТипаЗапись, ПрефиксИмениТипаВыборка)
	
	Периодический = Неопределено;
	
	Имя					= ОбъектМД.Имя;
	ТипСсылкиСтрокой	= ПрефиксИмениТипаЗапись + "." + Имя;
	ТипСсылки			= Тип(ТипСсылкиСтрокой);
	Структура = СтруктураПараметровМенеджера(Имя, ИмяТипа, ТипСсылкиСтрокой, Менеджер, ОбъектМД);
	
	Если ИмяТипа = "РегистрСведений" Тогда
		
		Периодический = (ОбъектМД.ПериодичностьРегистраСведений <> Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический);
		ПодчиненныйРегистратору = (ОбъектМД.РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору);
		
		Структура.Вставить("Периодический", Периодический);
		Структура.Вставить("ПодчиненныйРегистратору", ПодчиненныйРегистратору);
		
	КонецЕсли;	
	
	Менеджеры.Вставить(ТипСсылки, Структура);
		

	СтруктураДляПланаОбмена = СтруктураПараметровПланаОбмена(Имя, ТипСсылки, Ложь, Истина);

	МенеджерыДляПлановОбмена.Вставить(ОбъектМД, СтруктураДляПланаОбмена);
	
	
	ТипСсылкиСтрокой	= ПрефиксИмениТипаВыборка + "." + Имя;
	ТипСсылки			= Тип(ТипСсылкиСтрокой);
	Структура = СтруктураПараметровМенеджера(Имя, ИмяТипа, ТипСсылкиСтрокой, Менеджер, ОбъектМД);

	Если Периодический <> Неопределено Тогда
		
		Структура.Вставить("Периодический", Периодический);
		Структура.Вставить("ПодчиненныйРегистратору", ПодчиненныйРегистратору);	
		
	КонецЕсли;
	
	Менеджеры.Вставить(ТипСсылки, Структура);	
		
КонецПроцедуры

// Инициализирует переменную Менеджеры, содержащую соответствия типов объектов их свойствам.
//
// Параметры:
//  Нет.
// 
Процедура ИнициализацияМенеджеров()

	Менеджеры = Новый Соответствие;
	
	МенеджерыДляПлановОбмена = Новый Соответствие;
    	
	// ССЫЛКИ
	
	Для каждого ОбъектМД Из Метаданные.Справочники Цикл
		
		ДополнитьМассивМенеджеровСсылочнымТипом(Менеджеры, МенеджерыДляПлановОбмена, ОбъектМД, "Справочник", Справочники[ОбъектМД.Имя], "СправочникСсылка", Истина);
					
	КонецЦикла;

	Для каждого ОбъектМД Из Метаданные.Документы Цикл
		
		ДополнитьМассивМенеджеровСсылочнымТипом(Менеджеры, МенеджерыДляПлановОбмена, ОбъектМД, "Документ", Документы[ОбъектМД.Имя], "ДокументСсылка");
				
	КонецЦикла;

	Для каждого ОбъектМД Из Метаданные.ПланыВидовХарактеристик Цикл
		
		ДополнитьМассивМенеджеровСсылочнымТипом(Менеджеры, МенеджерыДляПлановОбмена, ОбъектМД, "ПланВидовХарактеристик", ПланыВидовХарактеристик[ОбъектМД.Имя], "ПланВидовХарактеристикСсылка", Истина);
				
	КонецЦикла;
	
	Для каждого ОбъектМД Из Метаданные.ПланыСчетов Цикл
		
		ДополнитьМассивМенеджеровСсылочнымТипом(Менеджеры, МенеджерыДляПлановОбмена, ОбъектМД, "ПланСчетов", ПланыСчетов[ОбъектМД.Имя], "ПланСчетовСсылка", Истина);
						
	КонецЦикла;
	
	Для каждого ОбъектМД Из Метаданные.ПланыВидовРасчета Цикл
		
		ДополнитьМассивМенеджеровСсылочнымТипом(Менеджеры, МенеджерыДляПлановОбмена, ОбъектМД, "ПланВидовРасчета", ПланыВидовРасчета[ОбъектМД.Имя], "ПланВидовРасчетаСсылка", Истина);
				
	КонецЦикла;
	
	Для каждого ОбъектМД Из Метаданные.ПланыОбмена Цикл
		
		ДополнитьМассивМенеджеровСсылочнымТипом(Менеджеры, МенеджерыДляПлановОбмена, ОбъектМД, "ПланОбмена", ПланыОбмена[ОбъектМД.Имя], "ПланОбменаСсылка");
				
	КонецЦикла;
	
	Для каждого ОбъектМД Из Метаданные.Задачи Цикл
		
		ДополнитьМассивМенеджеровСсылочнымТипом(Менеджеры, МенеджерыДляПлановОбмена, ОбъектМД, "Задача", Задачи[ОбъектМД.Имя], "ЗадачаСсылка");
				
	КонецЦикла;
	
	Для каждого ОбъектМД Из Метаданные.БизнесПроцессы Цикл
		
		ДополнитьМассивМенеджеровСсылочнымТипом(Менеджеры, МенеджерыДляПлановОбмена, ОбъектМД, "БизнесПроцесс", БизнесПроцессы[ОбъектМД.Имя], "БизнесПроцессСсылка");
		
		ИмяТипа = "ТочкаМаршрутаБизнесПроцесса";
		// ссылка на точки маршрута
		Имя              = ОбъектМД.Имя;
		Менеджер         = БизнесПроцессы[Имя].ТочкиМаршрута;
		СтрокаПоиска     = "";
		ТипСсылкиСтрокой = "ТочкаМаршрутаБизнесПроцессаСсылка." + Имя;
		ТипСсылки        = Тип(ТипСсылкиСтрокой);
		Структура = СтруктураПараметровМенеджера(Имя, ИмяТипа, ТипСсылкиСтрокой, Менеджер, ОбъектМД);
		Структура.Вставить("ПустаяСсылка", Неопределено);
		Структура.Вставить("СтрокаПоиска", СтрокаПоиска);
		Менеджеры.Вставить(ТипСсылки, Структура);
				
	КонецЦикла;
	
	// РЕГИСТРЫ

	Для каждого ОбъектМД Из Метаданные.РегистрыСведений Цикл
		
		ДополнитьМассивМенеджеровТипомРегистра(Менеджеры, ОбъектМД, "РегистрСведений", РегистрыСведений[ОбъектМД.Имя], "РегистрСведенийЗапись", "РегистрСведенийВыборка");
						
	КонецЦикла;

	Для каждого ОбъектМД Из Метаданные.РегистрыБухгалтерии Цикл
		
		ДополнитьМассивМенеджеровТипомРегистра(Менеджеры, ОбъектМД, "РегистрБухгалтерии", РегистрыБухгалтерии[ОбъектМД.Имя], "РегистрБухгалтерииЗапись", "РегистрБухгалтерииВыборка");
				
	КонецЦикла;
	
	Для каждого ОбъектМД Из Метаданные.РегистрыНакопления Цикл
		
		ДополнитьМассивМенеджеровТипомРегистра(Менеджеры, ОбъектМД, "РегистрНакопления", РегистрыНакопления[ОбъектМД.Имя], "РегистрНакопленияЗапись", "РегистрНакопленияВыборка");
						
	КонецЦикла;
	
	Для каждого ОбъектМД Из Метаданные.РегистрыРасчета Цикл
		
		ДополнитьМассивМенеджеровТипомРегистра(Менеджеры, ОбъектМД, "РегистрРасчета", РегистрыРасчета[ОбъектМД.Имя], "РегистрРасчетаЗапись", "РегистрРасчетаВыборка");
						
	КонецЦикла;
	
	ИмяТипа = "Перечисление";
	
	Для каждого ОбъектМД Из Метаданные.Перечисления Цикл
		
		Имя              = ОбъектМД.Имя;
		Менеджер         = Перечисления[Имя];
		ТипСсылкиСтрокой = "ПеречислениеСсылка." + Имя;
		ТипСсылки        = Тип(ТипСсылкиСтрокой);
		Структура = СтруктураПараметровМенеджера(Имя, ИмяТипа, ТипСсылкиСтрокой, Менеджер, ОбъектМД);
		Структура.Вставить("ПустаяСсылка", Перечисления[Имя].ПустаяСсылка());

		Менеджеры.Вставить(ТипСсылки, Структура);
		
	КонецЦикла;	
	
	// Константы
	ИмяТипа             = "Константы";
	ОбъектМД            = Метаданные.Константы;
	Имя					= "Константы";
	Менеджер			= Константы;
	ТипСсылкиСтрокой	= "КонстантыНабор";
	ТипСсылки			= Тип(ТипСсылкиСтрокой);
	Структура = СтруктураПараметровМенеджера(Имя, ИмяТипа, ТипСсылкиСтрокой, Менеджер, ОбъектМД);
	Менеджеры.Вставить(ТипСсылки, Структура);
	
КонецПроцедуры

// Выполняет инициализация менеджеров объектов и всех сообщений протокола обмена данными.
//
// Параметры:
//  Нет.
// 
Процедура ИнициализироватьМенеджерыИСообщения() Экспорт
	
	Если Менеджеры = Неопределено Тогда
		ИнициализацияМенеджеров();
	КонецЕсли; 

	Если одСообщения = Неопределено Тогда
		ИнициализацияСообщений();
	КонецЕсли;
	
КонецПроцедуры

// Возвращаемое значение:
//   Структура:
//     * ВерсияФормата - Строка
//     * Ид - Строка
//     * Наименование - Строка
//     * ДатаВремяСоздания - Дата
//     * ВерсияПлатформыИсточника - Строка
//     * СинонимКонфигурацииИсточника - Строка
//     * ВерсияКонфигурацииИсточника - Строка
//     * Источник - Строка
//     * ВерсияПлатформыПриемника - Строка
//     * СинонимКонфигурацииПриемника - Строка
//     * ВерсияКонфигурацииПриемника - Строка
//     * Приемник - Строка
//     * ПослеЗагрузкиПравилОбмена - Строка
//     * ПередВыгрузкойДанных - Строка
//     * ПередПолучениемИзмененныхОбъектов - Строка
//     * ПослеПолученияИнформацииОбУзлахОбмена - Строка
//     * ПослеВыгрузкиДанных - Строка
//     * ПередОтправкойИнформацииОбУдалении - Строка
//     * ПередВыгрузкойОбъекта - Строка
//     * ПослеВыгрузкиОбъекта - Строка
//     * ПередЗагрузкойОбъекта - Строка
//     * ПослеЗагрузкиОбъекта - Строка
//     * ПередКонвертациейОбъекта - Строка
//     * ПередЗагрузкойДанных - Строка
//     * ПослеЗагрузкиДанных - Строка
//     * ПослеЗагрузкиПараметров - Строка
//     * ПриПолученииИнформацииОбУдалении - Строка
//
Функция Конвертация()
	Возврат Конвертация;
КонецФункции

// Возвращаемое значение:
//   Структура:
//     * Имя - Строка
//     * ИмяТипа - Строка
//     * ТипСсылкиСтрокой - Строка
//     * Менеджер - СправочникМенеджер
//                - ДокументМенеджер
//                - РегистрСведенийМенеджер
//                - и т.п.
//     * ОбъектМД - ОбъектМетаданныхСправочник
//                - ОбъектМетаданныхДокумент
//                - ОбъектМетаданныхРегистрСведений
//                - и т.п.
//     * ПКО - см. НайтиПравило
//
Функция Менеджеры(Тип)
	Возврат Менеджеры[Тип];
КонецФункции

Процедура СоздатьСтруктуруКонвертации()
	
	Конвертация  = Новый Структура("ПередВыгрузкойДанных, ПослеВыгрузкиДанных, ПередВыгрузкойОбъекта, ПослеВыгрузкиОбъекта, ПередКонвертациейОбъекта, ПередЗагрузкойОбъекта, ПослеЗагрузкиОбъекта, ПередЗагрузкойДанных, ПослеЗагрузкиДанных");
	
КонецПроцедуры

// Инициализирует реквизиты обработки и модульные переменные.
//
// Параметры:
//  Нет.
// 
Процедура ИнициализацияРеквизитовИМодульныхПеременных()

	КоличествоОбработанныхОбъектовДляОбновленияСтатуса = 100;
	
	ЗапоминатьЗагруженныеОбъекты     = Истина;
	ЧислоХранимыхЗагруженныхОбъектов = 5000;
	
	ПараметрыИнициализированы        = Ложь;
	
	ВестиДополнительныйКонтрольЗаписиВXML = Ложь;
	НепосредственноеЧтениеВИБПриемнике = Ложь;
	НеВыводитьНикакихИнформационныхСообщенийПользователю = Ложь;
	
	Менеджеры    = Неопределено;
	одСообщения  = Неопределено;
	
	ФлагОшибки   = Ложь;
	
	СоздатьСтруктуруКонвертации();
	
	Правила      = Новый Структура;
	Алгоритмы    = Новый Структура;
	ДопОбработки = Новый Структура;
	Запросы      = Новый Структура;

	Параметры    = Новый Структура;
	СобытияПослеЗагрузкиПараметров = Новый Структура;
	
	ПараметрыДопОбработок = Новый Структура;
	
	// Типы
	одТипСтрока                  = Тип("Строка");
	одТипБулево                  = Тип("Булево");
	одТипЧисло                   = Тип("Число");
	одТипДата                    = Тип("Дата");
	одТипХранилищеЗначения       = Тип("ХранилищеЗначения");
	одТипУникальныйИдентификатор = Тип("УникальныйИдентификатор");
	одТипДвоичныеДанные          = Тип("ДвоичныеДанные");
	одТипВидДвиженияНакопления   = Тип("ВидДвиженияНакопления");
	одТипУдалениеОбъекта         = Тип("УдалениеОбъекта");
	одТипВидСчета			     = Тип("ВидСчета");
	одТипТип                     = Тип("Тип");
	одТипСоответствие            = Тип("Соответствие");

	ЗначениеПустаяДата		   = Дата('00010101');
	
	мXMLПравила  = Неопределено;
	
	// Типы узлов xml
	
	одТипУзлаXML_КонецЭлемента  = ТипУзлаXML.КонецЭлемента;
	одТипУзлаXML_НачалоЭлемента = ТипУзлаXML.НачалоЭлемента;
	одТипУзлаXML_Текст          = ТипУзлаXML.Текст;


	мСписокМакетовПравилОбмена  = Новый СписокЗначений;

	Для каждого Макет Из Метаданные().Макеты Цикл
		мСписокМакетовПравилОбмена.Добавить(Макет.Синоним);
	КонецЦикла; 
	    	
	мФайлПротоколаДанных = Неопределено;
	
	ТипИнформационнойБазыДляПодключения = Истина;
	АутентификацияWindowsИнформационнойБазыДляПодключения = Ложь;
	ВерсияПлатформыИнформационнойБазыДляПодключения = "V8";
	ОткрыватьПротоколыОбменаПослеВыполненияОпераций = Ложь;
	ЗагружатьДанныеВРежимеОбмена = Истина;
	ЗаписыватьВИнформационнуюБазуТолькоИзмененныеОбъекты = Истина;
	ЗаписыватьРегистрыНаборамиЗаписей = Истина;
	ОптимизированнаяЗаписьОбъектов = Истина;
	ВыгружатьТолькоРазрешенные = Истина;
	ОбъектыПоСсылкеЗагружатьБезПометкиУдаления = Истина;	
	ИспользоватьОтборПоДатеДляВсехОбъектов = Истина;
	
	мСоответствиеПустыхЗначенийТипов = Новый Соответствие;
	мСоответствиеОписаниеТипов = Новый Соответствие;
	
	мБылиПрочитаныПравилаОбменаПриЗагрузке = Ложь;

	ОбработчикиСобытийЧитаемИзФайлаПравилОбмена = Истина;
	
	мРежимыОбработкиДанных = Новый Структура;
	мРежимыОбработкиДанных.Вставить("Выгрузка",                   0);
	мРежимыОбработкиДанных.Вставить("Загрузка",                   1);
	мРежимыОбработкиДанных.Вставить("ЗагрузкаПравилОбмена",       2);
	мРежимыОбработкиДанных.Вставить("ЭкспортОбработчиковСобытий", 3);
	
	РежимОбработкиДанных = мРежимыОбработкиДанных.Выгрузка;
	
	мРежимыОтладкиАлгоритмов = Новый Структура;
	мРежимыОтладкиАлгоритмов.Вставить("НеИспользовать",   0);
	мРежимыОтладкиАлгоритмов.Вставить("ПроцедурныйВызов", 1);
	мРежимыОтладкиАлгоритмов.Вставить("ИнтеграцияКода",   2);
	
	РежимОтладкиАлгоритмов = мРежимыОтладкиАлгоритмов.НеИспользовать;
	
	// Модули стандартных подсистем.
	Попытка
		// Вызов ВычислитьВБезопасномРежиме не требуется, т.к. для вычисления передается строковый литерал.
		МодульДатыЗапретаИзменения = Вычислить("ДатыЗапретаИзменения");
	Исключение
		МодульДатыЗапретаИзменения = Неопределено;
	КонецПопытки;
	
	РазделителиКонфигурации = Новый Массив;
	Для Каждого ОбщийРеквизит Из Метаданные.ОбщиеРеквизиты Цикл
		Если ОбщийРеквизит.РазделениеДанных = Метаданные.СвойстваОбъектов.РазделениеДанныхОбщегоРеквизита.Разделять Тогда
			РазделителиКонфигурации.Добавить(ОбщийРеквизит.Имя);
		КонецЕсли;
	КонецЦикла;
	РазделителиКонфигурации = Новый ФиксированныйМассив(РазделителиКонфигурации);
	
	ВременныйКаталогРаботыСФайлами = ПолучитьИмяВременногоФайла();
	УдалитьФайлы(ВременныйКаталогРаботыСФайлами);
	
КонецПроцедуры

Функция ОпределитьДостаточностьПараметровДляПодключенияКИнформационнойБазе(СтруктураПодключения, СтрокаПодключения = "", СтрокаСообщенияОбОшибке = "")
	
	НаличиеОшибок = Ложь;
	
	Если СтруктураПодключения.ФайловыйРежим  Тогда
		
		Если ПустаяСтрока(СтруктураПодключения.КаталогИБ) Тогда
			
			СтрокаСообщенияОбОшибке = НСтр("ru = 'Не задан каталог информационной базы-приемника'");
			
			СообщитьПользователю(СтрокаСообщенияОбОшибке);
			
			НаличиеОшибок = Истина;
			
		КонецЕсли;
		
		СтрокаПодключения = "File=""" + СтруктураПодключения.КаталогИБ + """";
	Иначе
		
		Если ПустаяСтрока(СтруктураПодключения.ИмяСервера) Тогда
			
			СтрокаСообщенияОбОшибке = НСтр("ru = 'Не задано имя сервера 1С:Предприятия информационной базы-приемника'");
			
			СообщитьПользователю(СтрокаСообщенияОбОшибке);
			
			НаличиеОшибок = Истина;
			
		КонецЕсли;
		
		Если ПустаяСтрока(СтруктураПодключения.ИмяИБНаСервере) Тогда
			
			СтрокаСообщенияОбОшибке = НСтр("ru = 'Не задано имя информационной базы-приемника на сервере 1С:Предприятия'");
			
			СообщитьПользователю(СтрокаСообщенияОбОшибке);
			
			НаличиеОшибок = Истина;
			
		КонецЕсли;		
		
		СтрокаПодключения = "Srvr = """ + СтруктураПодключения.ИмяСервера + """; Ref = """ + СтруктураПодключения.ИмяИБНаСервере + """";		
		
	КонецЕсли;
	
	Возврат НЕ НаличиеОшибок;	
	
КонецФункции

Функция ПодключитсяКИнформационнойБазе(СтруктураПодключения, СтрокаСообщенияОбОшибке = "")
	
	Перем СтрокаПодключения;
	
	ПараметровДостаточно = ОпределитьДостаточностьПараметровДляПодключенияКИнформационнойБазе(СтруктураПодключения, СтрокаПодключения, СтрокаСообщенияОбОшибке);
	
	Если Не ПараметровДостаточно Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Если Не СтруктураПодключения.АутентификацияWindows Тогда
		Если НЕ ПустаяСтрока(СтруктураПодключения.Пользователь) Тогда
			СтрокаПодключения = СтрокаПодключения + ";Usr = """ + СтруктураПодключения.Пользователь + """";
		КонецЕсли;
		Если НЕ ПустаяСтрока(СтруктураПодключения.Пароль) Тогда
			СтрокаПодключения = СтрокаПодключения + ";Pwd = """ + СтруктураПодключения.Пароль + """";
		КонецЕсли;
	КонецЕсли;
	
	// "V82" или "V83"
	ОбъектПодключения = СтруктураПодключения.ВерсияПлатформы;
	
	СтрокаПодключения = СтрокаПодключения + ";";
	
	Попытка
		
		ОбъектПодключения = ОбъектПодключения +".COMConnector";
		ТекCOMПодключение = Новый COMОбъект(ОбъектПодключения);
		ТекCOMОбъект = ТекCOMПодключение.Connect(СтрокаПодключения);
		
	Исключение
		
		СтрокаСообщенияОбОшибке = НСтр("ru = 'При попытке соединения с COM-сервером произошла следующая ошибка:
			|%1'");
		СтрокаСообщенияОбОшибке = ПодставитьПараметрыВСтроку(СтрокаСообщенияОбОшибке, 
			ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		
		СообщитьПользователю(СтрокаСообщенияОбОшибке);
		
		Возврат Неопределено;
		
	КонецПопытки;
	
	Возврат ТекCOMОбъект;
	
КонецФункции

// Функция возвращает часть строки после последнего встреченного символа в строке.
Функция ПолучитьСтрокуОтделеннойСимволом(Знач ИсходнаяСтрока, Знач СимволПоиска)
	
	ПозицияСимвола = СтрДлина(ИсходнаяСтрока);
	Пока ПозицияСимвола >= 1 Цикл
		
		Если Сред(ИсходнаяСтрока, ПозицияСимвола, 1) = СимволПоиска Тогда
						
			Возврат Сред(ИсходнаяСтрока, ПозицияСимвола + 1); 
			
		КонецЕсли;
		
		ПозицияСимвола = ПозицияСимвола - 1;	
	КонецЦикла;

	Возврат "";
  	
КонецФункции

// Выделяет из имени файла его расширение (набор символов после последней точки).
//
// Параметры:
//  ИмяФайла     - Строка - содержащая имя файла, неважно с именем каталога или без.
//
// Возвращаемое значение:
//   Строка - расширение файла.
//
Функция ПолучитьРасширениеИмениФайла(Знач ИмяФайла) Экспорт
	
	Расширение = ПолучитьСтрокуОтделеннойСимволом(ИмяФайла, ".");
	Возврат Расширение;
	
КонецФункции

Функция ПолучитьИмяПротоколаДляВторойИнформационнойБазыComСоединения() Экспорт
	
	Если Не ПустаяСтрока(ИмяФайлаПротоколаОбменаЗагрузка) Тогда
			
		Возврат ИмяФайлаПротоколаОбменаЗагрузка;	
		
	ИначеЕсли Не ПустаяСтрока(ИмяФайлаПротоколаОбмена) Тогда
		
		РасширениеФайлаПротокола = ПолучитьРасширениеИмениФайла(ИмяФайлаПротоколаОбмена);
		
		Если Не ПустаяСтрока(РасширениеФайлаПротокола) Тогда
							
			ИмяФайлаПротоколаВыгрузки = СтрЗаменить(ИмяФайлаПротоколаОбмена, "." + РасширениеФайлаПротокола, "");
			
		КонецЕсли;
		
		ИмяФайлаПротоколаВыгрузки = ИмяФайлаПротоколаВыгрузки + "_Загрузка";
		
		Если Не ПустаяСтрока(РасширениеФайлаПротокола) Тогда
			
			ИмяФайлаПротоколаВыгрузки = ИмяФайлаПротоколаВыгрузки + "." + РасширениеФайлаПротокола;	
			
		КонецЕсли;
		
		Возврат ИмяФайлаПротоколаВыгрузки;
		
	КонецЕсли;
	
	Возврат "";
	
КонецФункции

// Выполняет подключение к базе-приемнику по заданным параметрам.
// Возвращает проинициализированную обработку УниверсальныйОбменДаннымиXML базы-приемника,
// которая будет использоваться для загрузки данных в базу-приемник.
//
// Параметры:
//  Нет.
// 
//  Возвращаемое значение:
//    ОбработкаОбъект.УниверсальныйОбменДаннымиXML - обработка базы-приемника для загрузки данных в базу-приемник.
//
Функция ВыполнитьПодключениеКИБПриемнику() Экспорт
	
	РезультатПодключения = Неопределено;
	
	СтруктураПодключения = Новый Структура();
	СтруктураПодключения.Вставить("ФайловыйРежим", ТипИнформационнойБазыДляПодключения);
	СтруктураПодключения.Вставить("АутентификацияWindows", АутентификацияWindowsИнформационнойБазыДляПодключения);
	СтруктураПодключения.Вставить("КаталогИБ", КаталогИнформационнойБазыДляПодключения);
	СтруктураПодключения.Вставить("ИмяСервера", ИмяСервераИнформационнойБазыДляПодключения);
	СтруктураПодключения.Вставить("ИмяИБНаСервере", ИмяИнформационнойБазыНаСервереДляПодключения);
	СтруктураПодключения.Вставить("Пользователь", ПользовательИнформационнойБазыДляПодключения);
	СтруктураПодключения.Вставить("Пароль", ПарольИнформационнойБазыДляПодключения);
	СтруктураПодключения.Вставить("ВерсияПлатформы", ВерсияПлатформыИнформационнойБазыДляПодключения);
	
	ОбъектПодключения = ПодключитсяКИнформационнойБазе(СтруктураПодключения);
	
	Если ОбъектПодключения = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Попытка
		РезультатПодключения = ОбъектПодключения.Обработки.УниверсальныйОбменДаннымиXML.Создать();
	Исключение
		
		Текст = НСтр("ru = 'При попытке создания обработки %1 произошла ошибка: %2'");
		Текст = ПодставитьПараметрыВСтроку(Текст, Метаданные().Имя, ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
		СообщитьПользователю(Текст);
		РезультатПодключения = Неопределено;
		
	КонецПопытки;
	
	Если РезультатПодключения <> Неопределено Тогда
		
		РезультатПодключения.ИспользоватьТранзакции = ИспользоватьТранзакции;	
		РезультатПодключения.КоличествоОбъектовНаТранзакцию = КоличествоОбъектовНаТранзакцию;
		
		РезультатПодключения.ФлагРежимОтладки = ФлагРежимОтладки;
		
		РезультатПодключения.ИмяФайлаПротоколаОбмена = ПолучитьИмяПротоколаДляВторойИнформационнойБазыComСоединения();
								
		РезультатПодключения.ДописыватьДанныеВПротоколОбмена = ДописыватьДанныеВПротоколОбмена;
		РезультатПодключения.ВыводВПротоколИнформационныхСообщений = ВыводВПротоколИнформационныхСообщений;
		
		РезультатПодключения.РежимОбмена = "Загрузка";
		
	КонецЕсли;
	
	Возврат РезультатПодключения;
	
КонецФункции

// Выполняет удаление объектов заданного типа по правилам очистки данных
// (физическое удаление или пометка на удаление).
//
// Параметры:
//  ИмяТипаДляУдаления - Строка - имя типа в строковом представлении.
// 
Процедура УдалитьОбъектыТипа(ИмяТипаДляУдаления) Экспорт
	
	ТипДанныхДляУдаления = Тип(ИмяТипаДляУдаления);
	
	Менеджер = Менеджеры[ТипДанныхДляУдаления];
	ИмяТипа  = Менеджер.ИмяТипа;
	Свойства = Менеджеры[ТипДанныхДляУдаления];
	
	Правило = Новый Структура("Имя,Непосредственно,ПередУдалением", "УдалениеОбъекта", Истина, "");
					
	Выборка = ПолучитьВыборкуДляВыгрузкиОчисткиДанных(Свойства, ИмяТипа, Истина, Истина, Ложь);
	
	Пока Выборка.Следующий() Цикл
		
		Если ИмяТипа =  "РегистрСведений" Тогда
			
			МенеджерЗаписи = Свойства.Менеджер.СоздатьМенеджерЗаписи(); 
			ЗаполнитьЗначенияСвойств(МенеджерЗаписи, Выборка);
								
			УдалениеОбъектаВыборки(МенеджерЗаписи, Правило, Свойства, Неопределено);
				
		Иначе
				
			УдалениеОбъектаВыборки(Выборка.Ссылка.ПолучитьОбъект(), Правило, Свойства, Неопределено);
				
		КонецЕсли;
			
	КонецЦикла;	
	
КонецПроцедуры

Процедура ДополнитьСлужебныеТаблицыКолонками()
	
	ИнициализацияТаблицыПравилКонвертации();
	ИнициализацияТаблицыПравилВыгрузки();
	ИнициализацияТаблицыПравилОчистки();
	ИнициализацияТаблицыНастройкиПараметров();	
	
КонецПроцедуры

Функция ПолучитьНовоеУникальноеИмяВременногоФайла(СтароеИмяВременногоФайла, Расширение = "txt")
	
	УдалитьВременныеФайлы(СтароеИмяВременногоФайла);
	
	Возврат ПолучитьИмяВременногоФайла(Расширение);
	
КонецФункции 

Процедура ИнициализацияСтруктурыИменОбработчиков()
	
	// Обработчики Конвертации.
	ИменаОбработчиковКонвертации = Новый Структура;
	ИменаОбработчиковКонвертации.Вставить("ПередВыгрузкойДанных");
	ИменаОбработчиковКонвертации.Вставить("ПослеВыгрузкиДанных");
	ИменаОбработчиковКонвертации.Вставить("ПередВыгрузкойОбъекта");
	ИменаОбработчиковКонвертации.Вставить("ПослеВыгрузкиОбъекта");
	ИменаОбработчиковКонвертации.Вставить("ПередКонвертациейОбъекта");
	ИменаОбработчиковКонвертации.Вставить("ПередОтправкойИнформацииОбУдалении");
	ИменаОбработчиковКонвертации.Вставить("ПередПолучениемИзмененныхОбъектов");
	
	ИменаОбработчиковКонвертации.Вставить("ПередЗагрузкойОбъекта");
	ИменаОбработчиковКонвертации.Вставить("ПослеЗагрузкиОбъекта");
	ИменаОбработчиковКонвертации.Вставить("ПередЗагрузкойДанных");
	ИменаОбработчиковКонвертации.Вставить("ПослеЗагрузкиДанных");
	ИменаОбработчиковКонвертации.Вставить("ПриПолученииИнформацииОбУдалении");
	ИменаОбработчиковКонвертации.Вставить("ПослеПолученияИнформацииОбУзлахОбмена");
	
	ИменаОбработчиковКонвертации.Вставить("ПослеЗагрузкиПравилОбмена");
	ИменаОбработчиковКонвертации.Вставить("ПослеЗагрузкиПараметров");
	
	// Обработчики ПКО.
	ИменаОбработчиковПКО = Новый Структура;
	ИменаОбработчиковПКО.Вставить("ПередВыгрузкой");
	ИменаОбработчиковПКО.Вставить("ПриВыгрузке");
	ИменаОбработчиковПКО.Вставить("ПослеВыгрузки");
	ИменаОбработчиковПКО.Вставить("ПослеВыгрузкиВФайл");
	
	ИменаОбработчиковПКО.Вставить("ПередЗагрузкой");
	ИменаОбработчиковПКО.Вставить("ПриЗагрузке");
	ИменаОбработчиковПКО.Вставить("ПослеЗагрузки");
	
	ИменаОбработчиковПКО.Вставить("ПоследовательностьПолейПоиска");
	
	// Обработчики ПКС.
	ИменаОбработчиковПКС = Новый Структура;
	ИменаОбработчиковПКС.Вставить("ПередВыгрузкой");
	ИменаОбработчиковПКС.Вставить("ПриВыгрузке");
	ИменаОбработчиковПКС.Вставить("ПослеВыгрузки");

	// Обработчики ПКГС.
	ИменаОбработчиковПКГС = Новый Структура;
	ИменаОбработчиковПКГС.Вставить("ПередВыгрузкой");
	ИменаОбработчиковПКГС.Вставить("ПриВыгрузке");
	ИменаОбработчиковПКГС.Вставить("ПослеВыгрузки");
	
	ИменаОбработчиковПКГС.Вставить("ПередОбработкойВыгрузки");
	ИменаОбработчиковПКГС.Вставить("ПослеОбработкиВыгрузки");
	
	// Обработчики ПВД.
	ИменаОбработчиковПВД = Новый Структура;
	ИменаОбработчиковПВД.Вставить("ПередОбработкой");
	ИменаОбработчиковПВД.Вставить("ПослеОбработки");
	ИменаОбработчиковПВД.Вставить("ПередВыгрузкой");
	ИменаОбработчиковПВД.Вставить("ПослеВыгрузки");
	
	// Обработчики ПОД.
	ИменаОбработчиковПОД = Новый Структура;
	ИменаОбработчиковПОД.Вставить("ПередОбработкой");
	ИменаОбработчиковПОД.Вставить("ПослеОбработки");
	ИменаОбработчиковПОД.Вставить("ПередУдалением");
	
	// Глобальная структура с именами обработчиков.
	ИменаОбработчиков = Новый Структура;
	ИменаОбработчиков.Вставить("Конвертация", ИменаОбработчиковКонвертации); 
	ИменаОбработчиков.Вставить("ПКО",         ИменаОбработчиковПКО); 
	ИменаОбработчиков.Вставить("ПКС",         ИменаОбработчиковПКС); 
	ИменаОбработчиков.Вставить("ПКГС",        ИменаОбработчиковПКГС); 
	ИменаОбработчиков.Вставить("ПВД",         ИменаОбработчиковПВД); 
	ИменаОбработчиков.Вставить("ПОД",         ИменаОбработчиковПОД); 
	
КонецПроцедуры  

// Возвращаемое значение:
//   Структура - описание менеджера типа значения:
//     * Имя - Строка
//     * ИмяТипа - Строка
//     * ТипСсылкиСтрокой - Строка
//     * Менеджер - Произвольный
//     * ОбъектМД - ОбъектМетаданных
//     * ВозможенПоискПоПредопределенным - Булево
//     * ПКО - Произвольный
//
Функция СтруктураПараметровМенеджера(Имя, ИмяТипа, ТипСсылкиСтрокой, Менеджер, ОбъектМД)
	Структура = Новый Структура();
	Структура.Вставить("Имя", Имя);
	Структура.Вставить("ИмяТипа", ИмяТипа);
	Структура.Вставить("ТипСсылкиСтрокой", ТипСсылкиСтрокой);
	Структура.Вставить("Менеджер", Менеджер);
	Структура.Вставить("ОбъектМД", ОбъектМД);
	Структура.Вставить("ВозможенПоискПоПредопределенным", Ложь);
	Структура.Вставить("ПКО");
	Возврат Структура;
КонецФункции

Функция СтруктураПараметровПланаОбмена(Имя, ТипСсылки, ЭтоСсылочныйТип, ЭтоРегистр)
	Структура = Новый Структура();
	Структура.Вставить("Имя",Имя);
	Структура.Вставить("ТипСсылки",ТипСсылки);
	Структура.Вставить("ЭтоСсылочныйТип",ЭтоСсылочныйТип);
	Структура.Вставить("ЭтоРегистр",ЭтоРегистр);
	Возврат Структура;
КонецФункции

////////////////////////////////////////////////////////////////////////////////
// Процедуры и функции из базовой функциональности для обеспечения автономности.

Функция ПодсистемаСуществует(ПолноеИмяПодсистемы) Экспорт
	
	ИменаПодсистем = ИменаПодсистем();
	Возврат ИменаПодсистем.Получить(ПолноеИмяПодсистемы) <> Неопределено;
	
КонецФункции

Функция ИменаПодсистем() Экспорт
	
	Возврат Новый ФиксированноеСоответствие(ИменаПодчиненныхПодсистем(Метаданные));
	
КонецФункции

Функция ИменаПодчиненныхПодсистем(РодительскаяПодсистема)
	
	Имена = Новый Соответствие;
	
	Для Каждого ТекущаяПодсистема Из РодительскаяПодсистема.Подсистемы Цикл
		
		Имена.Вставить(ТекущаяПодсистема.Имя, Истина);
		ИменаПодчиненных = ИменаПодчиненныхПодсистем(ТекущаяПодсистема);
		
		Для каждого ИмяПодчиненной Из ИменаПодчиненных Цикл
			Имена.Вставить(ТекущаяПодсистема.Имя + "." + ИмяПодчиненной.Ключ, Истина);
		КонецЦикла;
	КонецЦикла;
	
	Возврат Имена;
	
КонецФункции

Функция ОбщийМодуль(Имя) Экспорт
	
	Если Метаданные.ОбщиеМодули.Найти(Имя) <> Неопределено Тогда
		Модуль = Вычислить(Имя);
	Иначе
		Модуль = Неопределено;
	КонецЕсли;
	
	Если ТипЗнч(Модуль) <> Тип("ОбщийМодуль") Тогда
		ВызватьИсключение ПодставитьПараметрыВСтроку(НСтр("ru = 'Общий модуль ""%1"" не найден.'"), Имя);
	КонецЕсли;
	
	Возврат Модуль;
	
КонецФункции

Процедура СообщитьПользователю(ТекстСообщенияПользователю) Экспорт
	
	Сообщение = Новый СообщениеПользователю;
	Сообщение.Текст = ТекстСообщенияПользователю;
	Сообщение.Сообщить();
	
КонецПроцедуры

Функция ПодставитьПараметрыВСтроку(Знач СтрокаПодстановки,
	Знач Параметр1, Знач Параметр2 = Неопределено, Знач Параметр3 = Неопределено)
	
	СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%1", Параметр1);
	СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%2", Параметр2);
	СтрокаПодстановки = СтрЗаменить(СтрокаПодстановки, "%3", Параметр3);
	
	Возврат СтрокаПодстановки;
	
КонецФункции

Функция ИмяПредопределенного(Ссылка)
	
	ТекстЗапроса =
	"ВЫБРАТЬ
	|	ПсевдонимЗаданнойТаблицы.ИмяПредопределенныхДанных КАК ИмяПредопределенныхДанных
	|ИЗ
	|	&ИмяТаблицыМетаданных КАК ПсевдонимЗаданнойТаблицы
	|ГДЕ
	|	ПсевдонимЗаданнойТаблицы.Ссылка = &Ссылка";
	
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&ИмяТаблицыМетаданных", Ссылка.Метаданные().ПолноеИмя());
	
	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("Ссылка", Ссылка);
	Выборка = Запрос.Выполнить().Выбрать();
	Выборка.Следующий();
	
	Возврат Выборка.ИмяПредопределенныхДанных;
	
КонецФункции

Функция ЗначениеСсылочногоТипа(Значение)
	
	Тип = ТипЗнч(Значение);
	
	Возврат Тип <> Тип("Неопределено") 
		И (Справочники.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ Документы.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ Перечисления.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ ПланыВидовХарактеристик.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ ПланыСчетов.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ ПланыВидовРасчета.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ БизнесПроцессы.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ БизнесПроцессы.ТипВсеСсылкиТочекМаршрутаБизнесПроцессов().СодержитТип(Тип)
		ИЛИ Задачи.ТипВсеСсылки().СодержитТип(Тип)
		ИЛИ ПланыОбмена.ТипВсеСсылки().СодержитТип(Тип));
	
КонецФункции

Функция КодОсновногоЯзыка()
	Если ПодсистемаСуществует("СтандартныеПодсистемы.БазоваяФункциональность") Тогда
		МодульОбщегоНазначения = ОбщийМодуль("ОбщегоНазначения");
		Возврат МодульОбщегоНазначения.КодОсновногоЯзыка();
	КонецЕсли;
	Возврат Метаданные.ОсновнойЯзык.КодЯзыка;
КонецФункции

#КонецОбласти

#КонецОбласти

#Область Инициализация

ИнициализацияРеквизитовИМодульныхПеременных();
ДополнитьСлужебныеТаблицыКолонками();
ИнициализацияСтруктурыИменОбработчиков();

#КонецОбласти

#Иначе
ВызватьИсключение НСтр("ru = 'Недопустимый вызов объекта на клиенте.'");
#КонецЕсли